Changelog
12.0.0 (2023-08-17)
NOTE: This combines all changelog entries for prereleases of v12.0.0.
Although this is a complete rewrite of our SDK, we've strived to keep breakages to a minimum and expect our users to upgrade from v11 without any significant changes to their code-base.
Realm.BSON
, to simplify the new SDK we want to export only the BSON types that our SDK database component supports (ObjectId, Decimal128 and UUID). See #4934.Realm.Object
via the standard Object.keys(obj)
. As a side-effect we stopped supporting the object spread operator {...obj}
and introduced Realm.Object#keys()
, Realm.Object#entries()
and Realm.Object#toJSON()
methods were introduced as a workaround. The new SDK wraps its accessor objects in a Proxy trapping the ownKeys operation which enables calls to the standard Object.keys(obj)
and the spread operator {...obj}
to work correctly, with minimal performance impact on normal accesses. Therefore, we are deprecating the APIs with the @deprecation annotation and a console.warn
when calling RealmObject#keys()
and RealmObject#entries()
. RealmObject#toJSON
still serves the purpose of producing a circularly referencing object graph. We would love the community's feedback on this!Results
, List
and Set
used to inherit directly from Collection
but now inherits from an abstract OrderedCollection
, which extends Collection
.PropertySchema
and PropertySchemaShorthand
types.)// Example object schema
const TaskSchema = {
name: "Task",
properties: {
description: /* property schema (shorthand or object form) */,
},
};
// Explicitness
"[]" // Bad (previously parsed as implicit "mixed")
"mixed[]" // Good
{ type: "list" } // Bad
{ type: "list", objectType: "mixed" } // Good
// Mixing shorthand and object form
{ type: "int[]" } // Bad
"int[]" // Good
{ type: "list", objectType: "int" } // Good
{ type: "int?" } // Bad
"int?" // Good
{ type: "int", optional: true } // Good
// Specifying object types
{ type: "SomeType" } // Bad
"SomeType" // Good
{ type: "object", objectType: "SomeType" } // Good
{ type: "object[]", objectType: "SomeType" } // Bad
"SomeType[]" // Good
{ type: "list", objectType: "SomeType" } // Good
{ type: "linkingObjects", objectType: "SomeType", property: "someProperty" } // Good
instanceof SomeClass
checks, however, code which is directly using prototype or constructor comparisons will fail:Object.getPrototypeOf(object) == CustomObject.prototype // No longer works
object.constructor == CustomObject // No longer works
Symbol
type). In the new SDK, using a Symbol as a key in a dictionary will throw.SubscriptionSet
, since (a) the team saw little actual use-case for it, (b) it would bloat our SDK code, and (c) there is a simple workaround if needed (spreading into an array [...realm.subscriptions]
). (The property length
is available.) Again, something we would love feedback on.ObjectPropsType
, UserMap
, UserType
, BaseFunctionsFactory
, AuthProviders
, PropertyType
, HTTP
, *Details
interfaces of the EmailPasswordAuthClient
and AuthError
types, since they weren't used internally and not expected to be used by users. Moreover, most of these are very simple to type out for any user relying on it. Similarly, the DictionaryBase
type was introduced to help work around an issue (declaring string index accessors on a class with methods) in our declarations. We consider it an internal detail that got introduced as part of our public API by accident; thus, we ask users to use the Dictionary
type directly. We also decided to rename the Session
class to SyncSession
since it’s now exported directly on the package namespace. Session
will still be available (but deprecated) as Realm.Sync.Session
. We’re no longer using the *Payload
types (they were only used by Realm Web) and we don’t expect end-users to be relying directly on these, hence they were deleted."list"
instead of "array"
.undefined
or some other default value when calling methods or accessing properties on the JS SyncSession
object, even if that would violate our declared TS types. Now, in v12, we will throw from all methods and property accessors in this case.SubscriptionsState
enum (will be removed in v13) in favor of the now-named SubscriptionSetState
. (#5773)Realm.setLogger
, that allows to setup a single static logger for the duration of the app lifetime. Differently from the now deprecated sync logger (that was setup with Sync.setLogger
), this new one will emit messages coming also from the local database, and not only from sync. It is also possible to change the log level during the whole duration of the app lifetime with Realm.setLogLevel
. (#2546)CompensatingWriteError
which indicates that one or more object changes have been reverted by the server.
This can happen when the client creates/updates objects that do not match any subscription, or performs writes on an object it didn't have permission to access. (#5599)Results
instance via Results.subscribe()
(asynchronous) and Results.unsubscribe()
(synchronous). (#5772)
WaitForSync
enum specifying whether to wait or not wait for subscribed objects to be downloaded before resolving the promise returned from Results.subscribe()
.SubscriptionOptions
to take a WaitForSync
behavior and a maximum waiting timeout before returning from Results.subscribe()
.MutableSubscriptionSet.removeUnnamed()
for removing only unnamed subscriptions.const peopleOver20 = await realm
.objects("Person")
.filtered("age > 20")
.subscribe({
name: "peopleOver20",
behavior: WaitForSync.FirstTime, // Default
timeout: 2000,
});
// ...
peopleOver20.unsubscribe();
CanonicalGeoPoint
can be queried. (#5850)
geoWithin
operator in the query string to Results.filtered()
.GeoCircle
type, defined by its center and radius in radians), box (GeoBox
type, defined by its bottom left and upper right corners) and polygon (GeoPolygon
type, defined by its vertices).kmToRadians()
and miToRadians()
, that can be used to convert kilometers and miles to radians respectively, simplifying conversion of a circle's radius.import Realm, {
ObjectSchema,
GeoCircle,
CanonicalGeoPoint,
GeoPosition,
kmToRadians,
} from "realm";
// Example of a user-defined point class that can be queried using geospatial queries
class MyGeoPoint extends Realm.Object implements CanonicalGeoPoint {
coordinates!: GeoPosition;
type = "Point" as const;
static schema: ObjectSchema = {
name: "MyGeoPoint",
embedded: true,
properties: {
type: "string",
coordinates: "double[]",
},
};
}
class PointOfInterest extends Realm.Object {
name!: string;
location!: MyGeoPoint;
static schema: ObjectSchema = {
name: "PointOfInterest",
properties: {
name: "string",
location: "MyGeoPoint",
},
};
}
realm.write(() => {
realm.create(PointOfInterest, {
name: "Copenhagen",
location: {
coordinates: [12.558892784045568, 55.66717839648401],
type: "Point",
} as MyGeoPoint
});
realm.create(PointOfInterest, {
name: "New York",
location: {
coordinates: [-73.92474936213434, 40.700090994927415],
type: "Point",
} as MyGeoPoint
});
});
const pois = realm.objects(PointOfInterest);
const berlinCoordinates: GeoPoint = [13.397255909303222, 52.51174463251085];
const radius = kmToRadians(500); //500 km = 0.0783932519 rad
// Circle with a radius of 500kms centered in Berlin
const circleShape: GeoCircle = {
center: berlinCoordinates,
distance: radius,
};
// All points of interest in a 500kms radius from Berlin
let result = pois.filtered("location geoWithin $0", circleShape);
// Equivalent string query without arguments
result = pois.filtered("location geoWithin geoCircle([13.397255909303222, 52.51174463251085], 0.0783932519)");
SchemaParseError
(or one of its subtypes ObjectSchemaParseError
and PropertySchemaParseError
) rather than an AssertionError
or Error
. (#5198)SSLConfiguration
with a custom function for validating the server's SSL certificate. (#5485)PropertySchema.indexed
with the full-text
option, that allows to create an index for full-text search queries. (#5755)TRUEPREDICATE SORT(meta['age'])
. (realm/realm-core#5311)SyncError.logUrl
which contains the URL to the server log related to the sync error. (#5609)Realm.Results#length
) the number of exact matches (with no other query conditions) on a string
/int
/uuid
/objectId
property that has an index. This improvement will be especially noticeable if there are a large number of results returned (duplicate values).date
property that has an index.mixed
property that has an index.bool
property that has an index.mixed
property that does not have an index.THROW_ON_GLOBAL_REALM
which will enable throwing when the app is accessing the Realm
without first importing it from the Realm package.yarn
and the bson
dependency. (#6040)realm
binary is missing and provide guidance in the README.md
. (#5981)UpdateMode
recursively to all objects when passed to Realm.create()
. (#5933)Realm
was still open (realm/realm-core#6050).User.state
and changed the UserState
enum values to use pascal case to conform to the v11 implementation (except for UserState.Active
that we now deprecate in favor of UserState.LoggedIn
). (#5686)App.currentUser()
when being called on a new instance of App
(#5790)mixed
property with a string operator (contains
/like
/beginswith
/endswith
) or with case insensitivity. ([realm/realm-core#6376](https://github.com/realm/realm-core/issues/6376, since v10.5.0)mixed
property was returning case insensitive matches. For example querying for myIndexedMixed == "Foo"
would incorrectly match on values of "foo"
or "FOO"
. (realm/realm-core#6376, since v10.5.0)mixed
property on a non-empty class/objectType would crash with an assertion. (realm/realm-core#6376, since v10.5.0)Realm.App.Sync#pause()
could hold a reference to the database open after shutting down the sync session, preventing users from being able to delete the Realm. (realm/realm-core#6372, since v11.5.0)Realm.Results
and Realm.List
being in different orders on different devices. Moreover, some cases of the error message Invalid prior_size
may have be fixed too. (realm/realm-core#6191, since v10.15.0)Sync
as named export. #5649App.allUsers
to return a record with the User.id
as the key and the User
as the value. #5671@keys
in a Dictionary would throw an exception. (realm/realm-core#6831, since v12.0.0-rc.3)REALM_DISABLE_ANALYTICS
, and you can print out what is submitted by setting the environment variable REALM_PRINT_ANALYTICS
.