Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RKOTLIN-612] MongoClient API #1593

Merged
merged 44 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
99489a4
Initial scaffolding of API
rorbech Dec 4, 2023
8e37043
API experiments
rorbech Dec 5, 2023
77c5a68
More API experiments
rorbech Dec 5, 2023
673b7b2
Clean up API experiments
rorbech Dec 6, 2023
4a60867
Liniting
rorbech Dec 8, 2023
a6a1fb0
Clean up internal function call
rorbech Dec 8, 2023
f4a35f9
Fix nullability of findOne-variants and add custom serialization tests
rorbech Dec 13, 2023
1e221b9
More testing
rorbech Dec 15, 2023
bc3acb8
Another round for linting
rorbech Dec 18, 2023
82c85ac
Add CHANGELOG entry
rorbech Dec 18, 2023
e1c00c8
More test coverage
rorbech Dec 18, 2023
e492629
More testing
rorbech Dec 18, 2023
4818ad2
Update test after fixing bson deserializer
rorbech Dec 19, 2023
caa9e6b
Minor clean ups
rorbech Dec 19, 2023
58ded6d
Updates according to review comments
rorbech Dec 19, 2023
d5591da
Updates according to review comments
rorbech Dec 19, 2023
490b8ef
Merge branch 'main' into cr/mongo-client
rorbech Dec 19, 2023
9e65380
Clean up experimental kbson serialization annotation usage
rorbech Dec 20, 2023
b1e740e
Add data classes for UpdateOne and UpdateMany responses
rorbech Dec 20, 2023
27d2e51
Add documentation of collection operations
rorbech Dec 20, 2023
f46cad5
Apply suggestions from code review
rorbech Jan 2, 2024
7ce74af
Link serialization
rorbech Feb 13, 2024
988e69a
Merge branch 'main' into cr/mongo-client
rorbech Feb 15, 2024
d09e23a
Merge remote-tracking branch 'origin/cr/mongo-client' into cr/mongo-c…
rorbech Feb 15, 2024
88750e8
Updates according to review comments
rorbech Feb 15, 2024
63a300e
Typed link serialization
rorbech Apr 5, 2024
8743faa
Merge branch 'main' into cr/mongo-client
rorbech Apr 5, 2024
22ab855
Clean up and linting
rorbech Apr 5, 2024
51e3e29
Test upcoming kbson release
rorbech Apr 10, 2024
9d2d6b4
Merge branch 'main' into cr/mongo-client
rorbech Apr 10, 2024
7006b9e
Fix CopyFromRealmTests
rorbech Apr 10, 2024
81013a2
Use public available kbson 0.4.0
rorbech Apr 10, 2024
ab6d33e
Increace device farm timeout
rorbech Apr 11, 2024
40e01be
Remove primary key type generic type paramenter
rorbech May 6, 2024
b2f8008
Updates according to review comments
rorbech May 13, 2024
08525c9
Merge branch 'main' into cr/mongo-client
rorbech May 13, 2024
c40fce4
Add support for serialization of collections in mixed
rorbech May 13, 2024
2be6411
Add tests for MongoDBSerializer
rorbech May 15, 2024
0d56526
Add missing PublishedApi annotations
rorbech May 15, 2024
4bcba20
Merge branch 'main' into cr/mongo-client
rorbech May 17, 2024
53db033
Remove debug logging
rorbech May 17, 2024
98f9340
Updates according to review comments
rorbech May 21, 2024
656ba49
Another round for linting
rorbech May 21, 2024
a70ae52
Merge branch 'main' into cr/mongo-client
rorbech May 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/run-android-device-farm-test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ runs:
test_spec_file: test_spec-${{ inputs.app-id }}.yaml
test_spec_type: APPIUM_PYTHON_TEST_SPEC
remote_src: true
timeout: 3600
rorbech marked this conversation as resolved.
Show resolved Hide resolved
test_spec: |
version: 0.1
phases:
Expand Down
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This release will bump the Realm file format from version 23 to 24. Opening a fi
* Support for RealmLists and RealmDictionaries in `RealmAny`. (Issue [#1434](https://github.com/realm/realm-kotlin/issues/1434))
* Optimized `RealmList.indexOf()` and `RealmList.contains()` using Core implementation of operations instead of iterating elements and comparing them in Kotlin. (Issue [#1625](https://github.com/realm/realm-kotlin/pull/1666) [RKOTLIN-995](https://jira.mongodb.org/browse/RKOTLIN-995)).
* Add support for filtering logs by category. (Issue [#1691](https://github.com/realm/realm-kotlin/issues/1691) [JIRA](https://jira.mongodb.org/browse/RKOTLIN-1038))
* [Sync] Add Mongo Client API to access Atlas App Service collections. It can be accessed through `User.mongoClient`. (Issue [#972](https://github.com/realm/realm-kotlin/issues/972))
rorbech marked this conversation as resolved.
Show resolved Hide resolved

### Fixed
* None.
Expand Down Expand Up @@ -169,9 +170,9 @@ This release will bump the Realm file format from version 23 to 24. Opening a fi
* None.

### Enhancements
* [Sync] Added option to use managed WebSockets via OkHttp instead of Realm's built-in WebSocket client for Sync traffic (Only Android and JVM targets for now). Managed WebSockets offer improved support for proxies and firewalls that require authentication. This feature is currently opt-in and can be enabled by using `AppConfiguration.usePlatformNetworking()`. Managed WebSockets will become the default in a future version. (PR [#1528](https://github.com/realm/realm-kotlin/pull/1528)).
* `AutoClientResetFailed` exception now reports as the throwable cause any user exceptions that might occur during a client reset. (Issue [#1580](https://github.com/realm/realm-kotlin/issues/1580))
* The Unpacking of JVM native library will use the current library version instead of a calculated hash for the path. (Issue [#1617](https://github.com/realm/realm-kotlin/issues/1617)).
* [Sync] Added option to use managed WebSockets via OkHttp instead of Realm's built-in WebSocket client for Sync traffic (Only Android and JVM targets for now). Managed WebSockets offer improved support for proxies and firewalls that require authentication. This feature is currently opt-in and can be enabled by using `AppConfiguration.usePlatformNetworking()`. Managed WebSockets will become the default in a future version. (PR [#1528](https://github.com/realm/realm-kotlin/pull/1528)).
* [Sync] `AutoClientResetFailed` exception now reports as the throwable cause any user exceptions that might occur during a client reset. (Issue [#1580](https://github.com/realm/realm-kotlin/issues/1580))

### Fixed
* Cache notification callback JNI references at startup to ensure that symbols can be resolved in core callbacks. (Issue [#1577](https://github.com/realm/realm-kotlin/issues/1577))
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ object Versions {
const val jmh = "1.34" // https://github.com/openjdk/jmh
const val jmhPlugin = "0.6.6" // https://github.com/melix/jmh-gradle-plugin
const val junit = "4.13.2" // https://mvnrepository.com/artifact/junit/junit
const val kbson = "0.3.0" // https://github.com/mongodb/kbson
const val kbson = "0.4.0" // https://github.com/mongodb/kbson
// When updating the Kotlin version, also remember to update /examples/min-android-sample/build.gradle.kts
const val kotlin = "1.9.0" // https://github.com/JetBrains/kotlin and https://kotlinlang.org/docs/releases.html#release-details
const val kotlinJvmTarget = "1.8" // Which JVM bytecode version is kotlin compiled to.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ expect object RealmInterop {
app: RealmAppPointer,
user: RealmUserPointer,
name: String,
serviceName: String? = null,
serializedEjsonArgs: String, // as ejson
callback: AppCallback<String>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1710,14 +1710,16 @@ actual object RealmInterop {
)
}

@Suppress("LongParameterList")
actual fun realm_app_call_function(
app: RealmAppPointer,
user: RealmUserPointer,
name: String,
serviceName: String?,
serializedEjsonArgs: String,
callback: AppCallback<String>
) {
realmc.realm_app_call_function(app.cptr(), user.cptr(), name, serializedEjsonArgs, null, callback)
realmc.realm_app_call_function(app.cptr(), user.cptr(), name, serializedEjsonArgs, serviceName, callback)
}

actual fun realm_app_call_reset_password_function(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3262,6 +3262,7 @@ actual object RealmInterop {
app: RealmAppPointer,
user: RealmUserPointer,
name: String,
serviceName: String?,
serializedEjsonArgs: String,
callback: AppCallback<String>
) {
Expand All @@ -3270,7 +3271,7 @@ actual object RealmInterop {
user.cptr(),
name,
serializedEjsonArgs,
null,
serviceName,
staticCFunction { userData: CPointer<out CPointed>?, data: CPointer<ByteVarOf<Byte>>?, error: CPointer<realm_app_error_t>? ->
handleAppCallback(userData, error) {
data.safeKString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ public fun RealmInstant.toDuration(): Duration {
return epochSeconds.seconds + nanosecondsOfSecond.nanoseconds
}

internal fun Duration.toRealmInstant(): RealmInstant {
public fun Duration.toRealmInstant(): RealmInstant {
val seconds: Long = this.inWholeSeconds
val nanos: Duration = (this - seconds.seconds)
return RealmInstant.from(seconds, nanos.inWholeNanoseconds.toInt())
// We cannot do duration arithmetic as some operations on INFINITE and NEG_INFINITE will overflow
val nanos: Int = (this.inWholeNanoseconds - (seconds * RealmInstant.SEC_AS_NANOSECOND)).toInt()
return RealmInstant.from(seconds, nanos)
}

internal fun RealmInstant.restrictToMillisPrecision() =
toDuration().inWholeMilliseconds.milliseconds.toRealmInstant()

internal fun RealmInstant.asBsonDateTime() = BsonDateTime(toDuration().inWholeMilliseconds)
public inline fun RealmInstant.asBsonDateTime(): BsonDateTime = BsonDateTime(toDuration().inWholeMilliseconds)
public inline fun BsonDateTime.asRealmInstant(): RealmInstant = value.milliseconds.toRealmInstant()
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import kotlin.reflect.KProperty1
public interface RealmObjectCompanion {
public val `io_realm_kotlin_class`: KClass<out TypedRealmObject>
public val `io_realm_kotlin_className`: String
public val `io_realm_kotlin_fields`: Map<String, KProperty1<BaseRealmObject, Any?>>
public val `io_realm_kotlin_fields`: Map<String, Pair<KClass<*>, KProperty1<BaseRealmObject, Any?>>>
public val `io_realm_kotlin_primaryKey`: KMutableProperty1<*, *>?
public val `io_realm_kotlin_classKind`: RealmClassKind
public fun `io_realm_kotlin_schema`(): RealmClassImpl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,15 @@ internal fun <T : BaseRealmObject> RealmObjectReference<T>.toRealmObject(): T =
* Returns the [RealmObjectCompanion] associated with a given [BaseRealmObject]'s [KClass].
*/
internal inline fun KClass<*>.realmObjectCompanionOrNull(): RealmObjectCompanion? {
@Suppress("invisible_reference", "invisible_member")
return realmObjectCompanionOrNull(this)
}

/**
* Returns the [RealmObjectCompanion] associated with a given [BaseRealmObject]'s [KClass].
*/
internal inline fun <reified T : BaseRealmObject> KClass<T>.realmObjectCompanionOrThrow(): RealmObjectCompanion {
@Suppress("invisible_reference", "invisible_member")
return realmObjectCompanionOrThrow(this)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import io.realm.kotlin.internal.util.HEX_PATTERN
import io.realm.kotlin.internal.util.parseHex
import io.realm.kotlin.internal.util.toHexString
import io.realm.kotlin.types.RealmUUID
import org.mongodb.kbson.BsonBinary
import org.mongodb.kbson.BsonBinarySubType
import kotlin.experimental.and
import kotlin.experimental.or

Expand Down Expand Up @@ -101,3 +103,6 @@ public class RealmUUIDImpl : RealmUUID {
}
}
}

public inline fun RealmUUID.asBsonBinary(): BsonBinary = BsonBinary(BsonBinarySubType.UUID_STANDARD, bytes)
public inline fun BsonBinary.asRealmUUID(): RealmUUID = RealmUUID.from(data)
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ import kotlin.reflect.KClass
* associated [RealmObjectCompanion], in which case the `clazz` wasn't a user defined class
* implementing [BaseRealmObject] augmented by our compiler plugin.
*/
@PublishedApi
internal expect fun <T : Any> realmObjectCompanionOrNull(clazz: KClass<T>): RealmObjectCompanion?

/**
* Returns the [RealmObjectCompanion] associated with a given [BaseRealmObject]'s [KClass].
*/

@PublishedApi
internal expect fun <T : BaseRealmObject> realmObjectCompanionOrThrow(clazz: KClass<T>): RealmObjectCompanion
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public class CachedClassMetadata(
properties = interopProperties.map { propertyInfo: PropertyInfo ->
CachedPropertyMetadata(
propertyInfo,
companion?.io_realm_kotlin_fields?.get(propertyInfo.name)
companion?.io_realm_kotlin_fields?.get(propertyInfo.name)?.second
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2024 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.realm.kotlin.internal.schema

import io.realm.kotlin.internal.interop.CollectionType
import io.realm.kotlin.schema.ListPropertyType
import io.realm.kotlin.schema.MapPropertyType
import io.realm.kotlin.schema.RealmPropertyType
import io.realm.kotlin.schema.SetPropertyType
import io.realm.kotlin.schema.ValuePropertyType

public val RealmPropertyType.collectionType: CollectionType
get() {
return when (this) {
is ListPropertyType -> CollectionType.RLM_COLLECTION_TYPE_LIST
is MapPropertyType -> CollectionType.RLM_COLLECTION_TYPE_DICTIONARY
is SetPropertyType -> CollectionType.RLM_COLLECTION_TYPE_SET
is ValuePropertyType -> CollectionType.RLM_COLLECTION_TYPE_NONE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public object Validation {
* to that type, otherwise an IllegalArgumentException is thrown with the provided error message.
*/
@OptIn(ExperimentalContracts::class)
public inline fun <reified T : Any?> isType(arg: Any?, errorMessage: String) {
public inline fun <reified T : Any?> isType(arg: Any?, errorMessage: String = "Object '$arg' is not of type ${T::class.qualifiedName}") {
contract {
returns() implies (arg is T)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import io.realm.kotlin.ext.asRealmObject
import io.realm.kotlin.ext.toRealmDictionary
import io.realm.kotlin.ext.toRealmList
import io.realm.kotlin.ext.toRealmSet
import io.realm.kotlin.internal.toDuration
import io.realm.kotlin.internal.toRealmInstant
import io.realm.kotlin.internal.asBsonDateTime
import io.realm.kotlin.internal.asRealmInstant
import io.realm.kotlin.types.MutableRealmInt
import io.realm.kotlin.types.RealmAny
import io.realm.kotlin.types.RealmAny.Type
Expand All @@ -46,7 +46,6 @@ import org.mongodb.kbson.BsonBinarySubType
import org.mongodb.kbson.BsonDateTime
import org.mongodb.kbson.BsonObjectId
import org.mongodb.kbson.Decimal128
import kotlin.time.Duration.Companion.milliseconds

/**
* KSerializer implementation for [RealmList]. Serialization is done as a generic list structure,
Expand Down Expand Up @@ -250,12 +249,12 @@ public object RealmInstantKSerializer : KSerializer<RealmInstant> {
override val descriptor: SerialDescriptor = serializer.descriptor

override fun deserialize(decoder: Decoder): RealmInstant =
decoder.decodeSerializableValue(serializer).value.milliseconds.toRealmInstant()
decoder.decodeSerializableValue(serializer).asRealmInstant()

override fun serialize(encoder: Encoder, value: RealmInstant) {
encoder.encodeSerializableValue(
serializer = serializer,
value = BsonDateTime(value.toDuration().inWholeMilliseconds)
value = value.asBsonDateTime()
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import io.realm.kotlin.internal.platform.currentTime
public interface RealmInstant : Comparable<RealmInstant> {

public companion object {
private const val SEC_AS_NANOSECOND: Int = 1_000_000_000
internal const val SEC_AS_NANOSECOND: Int = 1_000_000_000

/**
* Minimum timestamp that can be stored in Realm.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ import kotlin.reflect.full.companionObjectInstance

// TODO OPTIMIZE Can we eliminate the reflective approach? Maybe by embedding the information
// through the compiler plugin or something similar to the Native findAssociatedObject
@PublishedApi
internal actual fun <T : Any> realmObjectCompanionOrNull(clazz: KClass<T>): RealmObjectCompanion? =
if (clazz.companionObjectInstance is RealmObjectCompanion) {
clazz.companionObjectInstance as RealmObjectCompanion
} else null

@PublishedApi
internal actual fun <T : BaseRealmObject> realmObjectCompanionOrThrow(clazz: KClass<T>): RealmObjectCompanion =
realmObjectCompanionOrNull(clazz)
?: error("Couldn't find companion object of class '${clazz.simpleName}'.\nA common cause for this is when the `io.realm.kotlin` is not applied to the Gradle module that contains the '${clazz.simpleName}' class.")
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ import kotlin.reflect.ExperimentalAssociatedObjects
import kotlin.reflect.KClass
import kotlin.reflect.findAssociatedObject

@PublishedApi
internal actual fun <T : Any> realmObjectCompanionOrNull(clazz: KClass<T>): RealmObjectCompanion? =
@OptIn(ExperimentalAssociatedObjects::class)
when (val associatedObject = clazz.findAssociatedObject<ModelObject>()) {
is RealmObjectCompanion -> associatedObject
else -> null
}

@PublishedApi
internal actual fun <T : BaseRealmObject> realmObjectCompanionOrThrow(clazz: KClass<T>): RealmObjectCompanion =
realmObjectCompanionOrNull(clazz)
?: error("Couldn't find companion object of class '${clazz.simpleName}'.\nA common cause for this is when the `io.realm.kotlin` is not applied to the Gradle module that contains the '${clazz.simpleName}' class.")
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import io.realm.kotlin.mongodb.auth.ApiKeyAuth
import io.realm.kotlin.mongodb.exceptions.AppException
import io.realm.kotlin.mongodb.ext.customDataAsBsonDocument
import io.realm.kotlin.mongodb.ext.profileAsBsonDocument
import io.realm.kotlin.mongodb.mongo.MongoClient
import io.realm.kotlin.mongodb.sync.SyncConfiguration
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson

/**
* A **user** holds the user's metadata and tokens for accessing App Services and Device Sync
Expand Down Expand Up @@ -201,6 +204,25 @@ public interface User {
*/
public suspend fun linkCredentials(credentials: Credentials): User

/**
* Get a [MongoClient] for accessing documents from App Service's _Data Source_.
*
* Serialization to and from EJSON is performed with [KBSON](https://github.com/mongodb/kbson)
* that supports the [Kotlin Serialization framework](https://github.com/Kotlin/kotlinx.serialization)
* and handles serialization to and from classes marked with [Serializable]. Serialization of
* realm objects and links have some caveats and requires special configuration. For full
* details see [MongoClient].
*
* @param serviceName the name of the data service.
* @param eJson the EJson serializer that the [MongoClient] should use to convert objects and
* primary keys with. Will default to the app's [EJson] instance configured with
* [AppConfiguration.Builder.ejson]. For details on configuration of serialization see
* [MongoClient].
* throws IllegalStateException if trying to obtain a [MongoClient] from a logged out [User].
*/
@ExperimentalKBsonSerializerApi
public fun mongoClient(serviceName: String, eJson: EJson? = null): MongoClient

/**
* Two Users are considered equal if they have the same user identity and are associated
* with the same app.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import io.realm.kotlin.internal.interop.CodeDescription

/**
* This exception is considered the top-level or "catch-all" for problems related to HTTP requests
* made towards App Services. This covers both HTTP transport problems, problems passing JSON
* or the server considering the request invalid, for whatever reason.
* made towards App Services. This covers both HTTP transport problems, or the server considering
* the request invalid, for whatever reason.
*
* Generally, reacting to this exception will be hard, except to log the error for further
* analysis. But in many cases a more specific subtype will be thrown, which will be easier to
Expand All @@ -31,7 +31,7 @@ import io.realm.kotlin.internal.interop.CodeDescription
* @see BadRequestException
* @see AuthException
*/
public open class ServiceException internal constructor(
public open class ServiceException @PublishedApi internal constructor(
message: String,
internal val errorCode: CodeDescription? = null
) : AppException(message)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2024 Realm Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.realm.kotlin.mongodb.ext

import io.realm.kotlin.mongodb.internal.MongoClientCollection
import io.realm.kotlin.mongodb.internal.MongoClientImpl
import io.realm.kotlin.mongodb.mongo.MongoClient
import io.realm.kotlin.mongodb.mongo.MongoCollection
import io.realm.kotlin.types.BaseRealmObject
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import org.mongodb.kbson.serialization.EJson

/**
* Get a [MongoCollection] that exposes methods to retrieve and update data from the remote
* collection of objects of schema type [T].
*
* Serialization to and from EJSON is performed with [KBSON](https://github.com/mongodb/kbson)
* and requires to opt-in to the experimental [ExperimentalKBsonSerializerApi]-feature.
*
* @param eJson the EJson serializer that the [MongoCollection] should use to convert objects and
* primary keys with. Will default to the databases [EJson] instance.
* @param T the schema type indicating which for which remote entities of the collection will be
* serialized from and to.
* @return a [MongoCollection] that will accept and return entities from the remote collection
* as [T] values.
*/
@ExperimentalKBsonSerializerApi
public inline fun <reified T : BaseRealmObject> MongoClient.collection(eJson: EJson? = null): MongoCollection<T> {
@Suppress("invisible_reference", "invisible_member")
return MongoClientCollection(this as MongoClientImpl, io.realm.kotlin.internal.platform.realmObjectCompanionOrThrow(T::class).io_realm_kotlin_className, eJson ?: this.eJson)
}
Loading
Loading