diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e89e36240..6181d9a198 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,38 @@ ## vNext (TBD) +> [!NOTE] +> This version bumps the Realm file format to version 24. It is not possible to downgrade to earlier versions. Older files will automatically be upgraded to the new file format. Files created by Realm JavaScript prior to v6.0.0, might not be upgradeable. **Only Realm Studio 15.0.0 or later** will be able to open the new file format. + ### Deprecations * None ### Enhancements -* None +* Updated bundled OpenSSL version to 3.2.0. ([realm/realm-core#7303](https://github.com/realm/realm-core/pull/7303)) +* Property keypath in RQL can be substituted with value given as argument. Use `$P` in query string. ([realm/realm-core#7033](https://github.com/realm/realm-core/issues/7033)) +* You can now use query substitution for the `@type` argument. ([realm/realm-core#7289](https://github.com/realm/realm-core/issues/7289)) +* Storage of `Decimal128` properties has been optimized so that the individual values will take up 0 bits (if all nulls), 32 bits, 64 bits or 128 bits depending on what is needed. ([realm/realm-core#6111]https://github.com/realm/realm-core/pull/6111)) +* Querying a specific entry in a collection (in particular 'first and 'last') is supported. ([realm/realm-core#4269](https://github.com/realm/realm-core/issues/4269)) +* Index on list of strings property now supported ([realm/realm-core#7142](https://github.com/realm/realm-core/pull/7142)) +* You can set the threshold levels for trace output on individual categories. ([realm/realm-core#7004](https://github.com/realm/realm-core/pull/7004)) +* Improved performance of RQL queries on a non-linked string property using `>`, `>=`, `<`, `<=` operators and fixed behavior that a null string should be evaluated as less than everything, previously nulls were not matched. ([realm/realm-core#3939](https://github.com/realm/realm-core/issues/3939)) +* Added support for using aggregate operations on Mixed properties in queries. ([realm/realm-core#7398](https://github.com/realm/realm-core/pull/7398)) ### Fixed -* ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?) -* None +* Aligned Dictionaries to Lists and Sets when they get cleared. ([#6205](https://github.com/realm/realm-core/issues/6205), since v10.3.0-rc.1) +* Fixed equality queries on a `Mixed` property with an index possibly returning the wrong result if values of different types happened to have the same StringIndex hash. ([realm/realm-core#6407](https://github.com/realm/realm-core/issues/6407), since v10.5.0-beta.1) +* `@count`/`@size` is now supported for `Mixed` properties. ([realm/realm-core#7280](https://github.com/realm/realm-core/issues/7280), since v10.0.0) +* Fixed queries like `indexed_property == NONE {x}` which mistakenly matched on only `x` instead of not `x`. This only applies when an indexed property with equality (`==`, or `IN`) matches with `NONE` on a list of one item. If the constant list contained more than one value then it was working correctly. ([realm/realm-java#7862](https://github.com/realm/realm-java/issues/7862), since v10.20.0) +* Uploading the changesets recovered during an automatic client reset recovery may lead to `Bad server version` errors and a new client reset. ([realm/realm-core#7279](https://github.com/realm/realm-core/issues/7279), since v12.5.0) +* Fixed crash in full text index using prefix search with no matches ([realm/realm-core#7309](https://github.com/realm/realm-core/issues/7309), since v12.2.0) +* Fixed a race condition when backing up Realm files before a client reset which could have lead to overwriting an existing file. ([realm/realm-core#7341](https://github.com/realm/realm-core/pull/7341)). ### Compatibility * React Native >= v0.71.4 -* Realm Studio v14.0.0. -* File format: generates Realms with format v23 (reads and upgrades file format v5 or later for non-synced Realm, upgrades file format v10 or later for synced Realms). +* Realm Studio v15.0.0. +* File format: generates Realms with format v24 (reads and upgrades file format v10 or later). ### Internal - - - +* Upgraded Realm Core from v13.26.0 to v14.1.0. ([#6499](https://github.com/realm/realm-js/issues/6499)) ## 12.6.2 (2024-03-04) @@ -26,11 +40,8 @@ * Fixed binding abstraction to allow access of certain properties (`$$typeof` for now) prior to its injection. ([#6522](https://github.com/realm/realm-js/issues/6522), since v12.6.1) * Added a missing dependency on `path-browserify`. ([#6522](https://github.com/realm/realm-js/issues/6522), since v12.6.1) -### Compatibility -* React Native >= v0.71.4 -* Realm Studio v14.0.0. -* File format: generates Realms with format v23 (reads and upgrades file format v5 or later for non-synced Realm, upgrades file format v10 or later for synced Realms). - +### Internal +* Using Realm Core v13.26.0. ## 12.6.1 (2024-02-26) diff --git a/integration-tests/assets/bundled.realm b/integration-tests/assets/bundled.realm index 758ed86258..c324776588 100644 Binary files a/integration-tests/assets/bundled.realm and b/integration-tests/assets/bundled.realm differ diff --git a/integration-tests/tests/src/tests/queries.ts b/integration-tests/tests/src/tests/queries.ts index e30791bf13..fe3cb1d3c3 100644 --- a/integration-tests/tests/src/tests/queries.ts +++ b/integration-tests/tests/src/tests/queries.ts @@ -327,7 +327,7 @@ describe("Queries", () => { ["Unsupported comparison between type", "boolCol == 0"], ["Unsupported comparison between type", "boolCol == 1"], ["Unsupported comparison between type", "boolCol == 'not a bool'"], - ["Unsupported comparison between type", "boolCol == $0", "not a bool"], + ["Cannot compare argument $0 with value", "boolCol == $0", "not a bool"], ["Unsupported comparison operator", "boolCol BEGINSWITH true"], ["Unsupported comparison operator", "boolCol CONTAINS true"], ["Unsupported comparison operator", "boolCol ENDSWITH true"], @@ -363,7 +363,7 @@ describe("Queries", () => { expectQueryException(this.realm, NullableTypesObject, [ ["Unsupported comparison between type", "dateCol == 'not a date'"], ["Unsupported comparison between type", "dateCol == 1"], - ["Unsupported comparison between type", "dateCol == $0", 1], + ["Cannot compare argument $0 with value", "dateCol == $0", 1], ]); }); }); @@ -401,7 +401,7 @@ describe("Queries", () => { expectQueryException(this.realm, NullableTypesObject, [ ["Unsupported comparison between type", "intCol == false"], ["Cannot convert", "intCol == 'not an int'"], - ["Unsupported comparison between type", "intCol == $0", "not an int"], + ["Cannot convert", "intCol == $0", "not an int"], ["Unsupported comparison operator", "intCol BEGINSWITH 1"], ["Unsupported comparison operator", "intCol CONTAINS 1"], ["Unsupported comparison operator", "intCol ENDSWITH 1"], @@ -446,7 +446,7 @@ describe("Queries", () => { expectQueryException(this.realm, NullableTypesObject, [ ["Unsupported comparison between type", "floatCol == false"], ["Cannot convert", "floatCol == 'not a float'"], - ["Unsupported comparison between type", "floatCol == $0", "not a float"], + ["Cannot convert", "floatCol == $0", "not a float"], ["Unsupported comparison operator", "floatCol BEGINSWITH 1"], ["Unsupported comparison operator", "floatCol CONTAINS 1"], ["Unsupported comparison operator", "floatCol ENDSWITH 1"], @@ -492,7 +492,7 @@ describe("Queries", () => { expectQueryException(this.realm, NullableTypesObject, [ ["Unsupported comparison between type", "doubleCol == false"], ["Cannot convert", "doubleCol == 'not a double'"], - ["Unsupported comparison between type", "doubleCol == $0", "not a double"], + ["Cannot convert", "doubleCol == $0", "not a double"], ["Unsupported comparison operator", "doubleCol BEGINSWITH 1"], ["Unsupported comparison operator", "doubleCol CONTAINS 1"], ["Unsupported comparison operator", "doubleCol ENDSWITH 1"], @@ -557,7 +557,7 @@ describe("Queries", () => { expectQueryException(this.realm, NullableTypesObject, [ ["Unsupported comparison between type", "stringCol == true"], ["Unsupported comparison between type", "stringCol == 123"], - ["Unsupported comparison operator", "stringCol CONTAINS $0", 1], + ["Cannot compare argument $0 with value", "stringCol CONTAINS $0", 1], ]); }); }); diff --git a/integration-tests/tests/src/tests/shared-realms.ts b/integration-tests/tests/src/tests/shared-realms.ts index 417190f2b7..f88d8f67af 100644 --- a/integration-tests/tests/src/tests/shared-realms.ts +++ b/integration-tests/tests/src/tests/shared-realms.ts @@ -17,22 +17,19 @@ //////////////////////////////////////////////////////////////////////////// import { expect } from "chai"; -import Realm, { List } from "realm"; +import Realm from "realm"; import { openRealmBefore, openRealmBeforeEach } from "../hooks"; import { createLocalConfig } from "../utils/open-realm"; +import { LogEntry } from "realm"; describe("SharedRealm operations", () => { describe("logger", () => { it("logger callback gets called", async function () { - type Log = { - message: string; - level: string; - }; - let logs: Log[] = []; - - Realm.setLogger((level, message) => { - logs.push({ level, message }); + let logs: LogEntry[] = []; + + Realm.setLogger((entry) => { + logs.push(entry); }); Realm.setLogLevel("all"); diff --git a/packages/realm/bindgen/CMakeLists.txt b/packages/realm/bindgen/CMakeLists.txt index 26fa9ad0ed..c7397bed2e 100644 --- a/packages/realm/bindgen/CMakeLists.txt +++ b/packages/realm/bindgen/CMakeLists.txt @@ -24,17 +24,21 @@ if(DEFINED CMAKE_JS_VERSION) elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") if(NODE_ARCH STREQUAL "arm") set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vendor/realm-core/tools/cmake/armv7-linux-gnueabihf.toolchain.cmake") + add_link_options(-fuse-ld=bfd) # due to how multiarch works in debian this is needed to link to the correct system libraries set(CMAKE_IGNORE_PATH "/usr/lib/x86_64-linux-gnu") elseif(NODE_ARCH STREQUAL "arm64") set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vendor/realm-core/tools/cmake/aarch64-linux-gnu.toolchain.cmake") set(CMAKE_IGNORE_PATH "/usr/lib/x86_64-linux-gnu") + add_link_options(-fuse-ld=gold) + add_link_options(-Wl,-z,noexecstack) + add_link_options(-Wl,--warn-execstack) elseif(NODE_ARCH STREQUAL "x64") set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vendor/realm-core/tools/cmake/x86_64-linux-gnu.toolchain.cmake") + add_link_options(-fuse-ld=gold) + add_link_options(-Wl,-z,noexecstack) + add_link_options(-Wl,--warn-execstack) endif() - add_link_options(-fuse-ld=gold) - add_link_options(-Wl,-z,noexecstack) - add_link_options(-Wl,--warn-execstack) endif() endif() diff --git a/packages/realm/bindgen/js_opt_in_spec.yml b/packages/realm/bindgen/js_opt_in_spec.yml index 7e0f340952..41e1a4b3c4 100644 --- a/packages/realm/bindgen/js_opt_in_spec.yml +++ b/packages/realm/bindgen/js_opt_in_spec.yml @@ -244,11 +244,16 @@ classes: - get_results_description - feed_buffer - make_ssl_verify_callback + - needs_file_format_upgrade + + LogCategoryRef: + methods: + - set_default_level_threshold + - get_category Logger: methods: - set_default_logger - - set_default_level_threshold ConstTableRef: methods: diff --git a/packages/realm/bindgen/src/templates/jsi.ts b/packages/realm/bindgen/src/templates/jsi.ts index 726d2140af..575d10e387 100644 --- a/packages/realm/bindgen/src/templates/jsi.ts +++ b/packages/realm/bindgen/src/templates/jsi.ts @@ -1084,7 +1084,7 @@ export function generate({ rawSpec, spec, file: makeFile }: TemplateContext): vo extern "C" { void realm_jsi_invalidate_caches() { // Clear the default logger, to prevent it from holding on to a pointer that was released - realm::util::Logger::set_default_level_threshold(realm::util::Logger::Level::off); + realm::util::LogCategory::get_category(realm::util::LogCategory::realm.get_name()).set_default_level_threshold(realm::util::Logger::Level::off); realm::util::Logger::set_default_logger(nullptr); // Close all cached Realms realm::_impl::RealmCoordinator::clear_all_caches(); diff --git a/packages/realm/bindgen/vendor/realm-core b/packages/realm/bindgen/vendor/realm-core index d12c38de2c..e1042b8504 160000 --- a/packages/realm/bindgen/vendor/realm-core +++ b/packages/realm/bindgen/vendor/realm-core @@ -1 +1 @@ -Subproject commit d12c38de2c8e4043ca1cd0934e1056c6eb214892 +Subproject commit e1042b8504e277820f14cb884bd6ee5578ef8cb6 diff --git a/packages/realm/src/Logger.ts b/packages/realm/src/Logger.ts index 5f753dde7b..48b09632ba 100644 --- a/packages/realm/src/Logger.ts +++ b/packages/realm/src/Logger.ts @@ -20,18 +20,141 @@ import { assert, binding } from "./internal"; export type LogLevel = "all" | "trace" | "debug" | "detail" | "info" | "warn" | "error" | "fatal" | "off"; +/** + * Log levels used by Realm + */ export enum NumericLogLevel { + /** + * Same as 'Trace' but with even more output. + */ All = 0, + /** + * A version of 'Debug' that allows for very high volume + * output. + */ Trace = 1, + /** + * Reveal information that can aid debugging, no longer paying + * attention to efficiency. + */ Debug = 2, + /** + * Same as 'Info', but prioritize completeness over minimalism. + */ Detail = 3, + /** + * Reveal information about what is going on, but in a + * minimalistic fashion to avoid general overhead from logging + * and to keep volume down. + */ Info = 4, + /** + * Be silent unless when there is an error or a warning. + */ Warn = 5, + /** + * Be silent unless when there is an error. + */ Error = 6, + /** + * Be silent unless when an error is fatal. + */ Fatal = 7, + /** + * Be silent. + */ Off = 8, } +export const LOG_CATEGORIES = [ + "Realm", + "Realm.Storage", + "Realm.Storage.Transaction", + "Realm.Storage.Query", + "Realm.Storage.Object", + "Realm.Storage.Notification", + "Realm.Sync", + "Realm.Sync.Client", + "Realm.Sync.Client.Session", + "Realm.Sync.Client.Changeset", + "Realm.Sync.Client.Network", + "Realm.Sync.Client.Reset", + "Realm.Sync.Server", + "Realm.App", + "Realm.SDK", +] as const; + +/** + * The category to receive log messages for. The {@link LogLevel} will + * always be set for a specific category. Setting the log level on one + * category, will automatically set the log level for any subcategory. + * @note + * When debugging, you might not need log messages from everything. To narrow + * this scope, log events can be grouped by category. + * + * `"Realm"` + * : Include logs from all categories. + * + * `"Realm.Storage"` + * : Database mutations and query operations. + * + * `"Realm.Storage.Transaction"` + * : Creating, advancing, and committing transactions. + * + * `"Realm.Storage.Query"` + * : Query operations. + * + * `"Realm.Storage.Object"` + * : Database mutations. + * + * `"Realm.Storage.Notification"` + * : Notifications of changes to the database. + * + * `"Realm.Sync"` + * : Activity related to Atlas Device Sync. + * + * `"Realm.Sync.Client"` + * : Activity related to Atlas Device Sync client operations. + * + * `"Realm.Sync.Client.Session"` + * : Connection level activity. + * + * `"Realm.Sync.Client.Changeset"` + * : Receiving, uploading, and integrating changesets. + * + * `"Realm.Sync.Client.Network"` + * : Low level network activity. + * + * `"Realm.Sync.Client.Reset"` + * : Client reset operations. + * + * `"Realm.Sync.Server"` + * : Activity related to Atlas Device Sync server operations. + * + * `"Realm.App"` + * : Log activity at the Atlas App level. + * + * `"Realm.SDK"` + * : Log activity at the SDK level. + */ +export type LogCategory = (typeof LOG_CATEGORIES)[number]; + +/** + * Log options to use when setting the log level. + */ +export type LogOptions = { + /** + * The log level to be used by the logger. + * @default "info" + */ + level: LogLevel; + /** + * The category to set the log level for. If omitted, the log level + * is set for all categories (`"Realm"`). + */ + category?: LogCategory; +}; + /** * A callback passed to `Realm.App.Sync.setLogger` when instrumenting the Atlas Device Sync client with a custom logger. * @param level - The level of the log entry between 0 and 8 inclusively. @@ -40,7 +163,64 @@ export enum NumericLogLevel { */ export type Logger = (level: NumericLogLevel, message: string) => void; -export type LoggerCallback = (level: LogLevel, message: string) => void; +/** + * A callback to be used as the logger. + * @param level - The level of the log entry. + * @param message - The message of the log entry. + * @since 12.0.0 + * @deprecated Will be removed in v13.0.0 + */ +export type LoggerCallback1 = (level: LogLevel, message: string) => void; + +/** + * Represents an entry in the log. + */ +export type LogEntry = { + /** + * The category (origin) of the log entry. + */ + category: LogCategory; + /** + * The level of the log entry. + */ + level: LogLevel; + /** + * The message of the log entry. + */ + message: string; +}; + +/** + * A callback to be used as the logger. + * @since 12.7.0 + */ +export type LoggerCallback2 = (entry: LogEntry) => void; +/** + * A callback to be used as the logger. + * @since 12.7.0 + */ +export type LoggerCallback = LoggerCallback1 | LoggerCallback2; + +/** @internal */ +export function toBindingLogger(logger: LoggerCallback) { + if (isLoggerWithLevel(logger)) { + return binding.Helpers.makeLogger((_, level, message) => { + logger(fromBindingLoggerLevelToLogLevel(level), message); + }); + } else { + return binding.Helpers.makeLogger((category, level, message) => { + logger({ + category: category as LogCategory, + level: fromBindingLoggerLevelToLogLevel(level), + message, + }); + }); + } +} + +function isLoggerWithLevel(logger: LoggerCallback): logger is LoggerCallback1 { + return logger.length === 2; +} /** @internal */ export function toBindingLoggerLevel(arg: LogLevel): binding.LoggerLevel { @@ -77,12 +257,12 @@ export function fromBindingLoggerLevelToLogLevel(arg: binding.LoggerLevel): LogL } /** @internal */ -export const defaultLogger: LoggerCallback = function (logLevel: LogLevel, message: string) { - const formattedLogMessage = `[${logLevel}] ${message}`; +export const defaultLogger: LoggerCallback2 = function ({ category, level, message }) { + const formattedLogMessage = `[${category} - ${level}] ${message}`; /* eslint-disable no-console */ - if (logLevel === "error" || logLevel === "fatal") { + if (level === "error" || level === "fatal") { console.error(formattedLogMessage); - } else if (logLevel === "warn") { + } else if (level === "warn") { console.warn(formattedLogMessage); } else { console.log(formattedLogMessage); diff --git a/packages/realm/src/ProgressRealmPromise.ts b/packages/realm/src/ProgressRealmPromise.ts index 9a12e6e343..3d58faf5eb 100644 --- a/packages/realm/src/ProgressRealmPromise.ts +++ b/packages/realm/src/ProgressRealmPromise.ts @@ -101,6 +101,7 @@ export class ProgressRealmPromise implements Promise { this.handle.resolve(realm); } else if (openBehavior === OpenRealmBehaviorType.DownloadBeforeOpen) { const { bindingConfig } = Realm.transformConfig(config); + // Construct an async open task this.task = binding.Realm.getSynchronizedRealm(bindingConfig); // If the promise handle gets rejected, we should cancel the open task diff --git a/packages/realm/src/Realm.ts b/packages/realm/src/Realm.ts index c7c973d8ca..b0d047247e 100644 --- a/packages/realm/src/Realm.ts +++ b/packages/realm/src/Realm.ts @@ -28,9 +28,14 @@ import { DefaultObject, INTERNAL, InitialSubscriptions, + LOG_CATEGORIES, List, + LogCategory, LogLevel, + LogOptions, LoggerCallback, + LoggerCallback1, + LoggerCallback2, MigrationCallback, ObjectSchema, ProgressRealmPromise, @@ -52,12 +57,12 @@ import { defaultLoggerLevel, extendDebug, flags, - fromBindingLoggerLevelToLogLevel, fromBindingRealmSchema, fs, normalizeObjectSchema, normalizeRealmSchema, toArrayBuffer, + toBindingLogger, toBindingLoggerLevel, toBindingSchema, toBindingSyncConfig, @@ -107,27 +112,66 @@ export class Realm { private static internals = new Set>(); /** - * Sets the log level. + * Sets the log level across all levels. * @param level - The log level to be used by the logger. The default value is `info`. * @note The log level can be changed during the lifetime of the application. * @since 12.0.0 + * @example + * Realm.setLogLevel("all"); + */ + static setLogLevel(level: LogLevel): void; + + /** + * Sets the log level for a specific category. + * @param options - The log options to use. + * @note The log level can be changed during the lifetime of the application. + * @since 12.7.0 + * @example + * Realm.setLogLevel({ category: "Realm", level: "all" }); */ - static setLogLevel(level: LogLevel) { - const bindingLoggerLevel = toBindingLoggerLevel(level); - binding.Logger.setDefaultLevelThreshold(bindingLoggerLevel); + static setLogLevel(options: LogOptions): void; + static setLogLevel(arg: LogLevel | LogOptions) { + const setLevel = (level: LogLevel, category = "Realm") => { + assert(LOG_CATEGORIES.includes(category as LogCategory), `Unexpected log category: '${category}'`); + const categoryRef = binding.LogCategoryRef.getCategory(category); + categoryRef.setDefaultLevelThreshold(toBindingLoggerLevel(level)); + }; + + if (typeof arg === "string") { + setLevel(arg); + } else { + setLevel(arg.level, arg.category); + } } /** * Sets the logger callback. * @param loggerCallback - The callback invoked by the logger. The default callback uses `console.log`, `console.warn` and `console.error`, depending on the level of the message. - * @note The logger callback needs to be setup before opening the first realm. + * @note The logger callback needs to be set up before opening the first Realm. + * @since 12.0.0 + * @example + * Realm.setLogger(({ category, level, message }) => { + * console.log(`[${category} - ${level}] ${message}`); + * }); + */ + static setLogger(loggerCallback: LoggerCallback2): void; + + /** + * Sets the logger callback. + * @param loggerCallback - The callback invoked by the logger. The default callback uses `console.log`, `console.warn` and `console.error`, depending on the level of the message. + * @note The logger callback needs to be set up before opening the first Realm. * @since 12.0.0 + * @deprecated Pass a callback taking a single object argument instead. + * @example + * Realm.setLogger((level, message) => { + * console.log(`[${level}] ${message}`); + * }); */ + static setLogger(loggerCallback: LoggerCallback1): void; + static setLogger(loggerCallback: LoggerCallback) { - const logger = binding.Helpers.makeLogger((level, message) => { - loggerCallback(fromBindingLoggerLevelToLogLevel(level), message); - }); - binding.Logger.setDefaultLogger(logger); + assert.function(loggerCallback); + binding.Logger.setDefaultLogger(toBindingLogger(loggerCallback)); } /** @@ -507,8 +551,8 @@ export class Realm { validateConfiguration(config); const { bindingConfig, schemaExtras } = Realm.transformConfig(config); debug("open", bindingConfig); - this.schemaExtras = schemaExtras; + this.schemaExtras = schemaExtras; fs.ensureDirectoryForFile(bindingConfig.path); this.internal = internalConfig.internal ?? binding.Realm.getSharedRealm(bindingConfig); if (flags.ALLOW_CLEAR_TEST_STATE) { @@ -1240,6 +1284,7 @@ export namespace Realm { export import InitialSubscriptions = internal.InitialSubscriptions; export import List = internal.List; export import LocalAppConfiguration = internal.LocalAppConfiguration; + export import LogEntry = internal.LogEntry; export import Logger = internal.Logger; export import LoggerCallback = internal.LoggerCallback; export import MapToDecorator = internal.MapToDecorator; diff --git a/packages/realm/src/app-services/Sync.ts b/packages/realm/src/app-services/Sync.ts index 691ee8f779..f8ecc51a73 100644 --- a/packages/realm/src/app-services/Sync.ts +++ b/packages/realm/src/app-services/Sync.ts @@ -46,7 +46,7 @@ export class Sync { /** @deprecated Will be removed in v13.0.0. Please use {@link Realm.setLogger}. */ static setLogger(app: App, logger: Logger) { - const factory = binding.Helpers.makeLoggerFactory((level, message) => { + const factory = binding.Helpers.makeLoggerFactory((_, level, message) => { logger(fromBindingLoggerLevelToNumericLogLevel(level), message); }); app.internal.syncManager.setLoggerFactory(factory); diff --git a/packages/realm/src/tests/schema-normalization.test.ts b/packages/realm/src/tests/schema-normalization.test.ts index 197e42c464..3db27d009e 100644 --- a/packages/realm/src/tests/schema-normalization.test.ts +++ b/packages/realm/src/tests/schema-normalization.test.ts @@ -751,6 +751,21 @@ describe("normalizePropertySchema", () => { }, { isPrimaryKey: true }, ); + + itNormalizes( + { + type: "list", + objectType: "string", + indexed: true, + }, + { + type: "list", + objectType: "string", + indexed: true, + optional: false, + }, + { isPrimaryKey: false }, + ); }); // ------------------------------------------------------------------------ diff --git a/scripts/changelog-header.sh b/scripts/changelog-header.sh index d364dda058..424f2dc1fe 100755 --- a/scripts/changelog-header.sh +++ b/scripts/changelog-header.sh @@ -18,8 +18,8 @@ CHANGELOG=$(cat <= v0.71.4 -* Realm Studio v14.0.0. -* File format: generates Realms with format v23 (reads and upgrades file format v5 or later for non-synced Realm, upgrades file format v10 or later for synced Realms). +* Realm Studio v15.0.0. +* File format: generates Realms with format v24 (reads and upgrades file format v10. ### Internal