Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: realm/realm-js
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d401cbeb41e76d42a45ba5dd4dc0b26eb71cbb9c
Choose a base ref
...
head repository: realm/realm-js
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5196e76d65c5faffa4246daeb3683ac6d0d17b35
Choose a head ref
  • 7 commits
  • 19 files changed
  • 6 contributors

Commits on Mar 16, 2023

  1. Prepare for 11.5.2 (#5560)

    * [11.5.2] Bump version
    
    * Update compatibility matrix
    
    * fix test
    
    ---------
    
    Co-authored-by: kneth <kneth@users.noreply.github.com>
    Co-authored-by: Kenneth Geisshirt <k@zigzak.net>
    3 people authored Mar 16, 2023
    Copy the full SHA
    46711a5 View commit details
  2. Prepare for vNext (#5567)

    Co-authored-by: kneth <kneth@users.noreply.github.com>
    github-actions[bot] and kneth authored Mar 16, 2023
    Copy the full SHA
    bf629d3 View commit details

Commits on Mar 22, 2023

  1. Disable ccache for node builds (#5602)

    * Disable ccache for node builds
    kneth authored Mar 22, 2023
    Copy the full SHA
    b7245b3 View commit details
  2. Reenable all tests (#5606)

    kneth authored Mar 22, 2023
    Copy the full SHA
    832fd6a View commit details

Commits on Mar 23, 2023

  1. Fix Create Call Signature (#5617)

    This allows the create static function to be used without a type error.  This reflects the change we made in bindgen.
    takameyer authored Mar 23, 2023
    Copy the full SHA
    22977ea View commit details
  2. Expose baseFilePath on App configuration (#5572)

    * Expose baseFilePath on App configuration
    * PR feedback
    kneth authored Mar 23, 2023
    Copy the full SHA
    430afad View commit details
  3. [11.6.0] Bump version

    kneth authored Mar 23, 2023
    Copy the full SHA
    5196e76 View commit details
2 changes: 2 additions & 0 deletions .github/workflows/pr-realm-js.yml
Original file line number Diff line number Diff line change
@@ -147,6 +147,8 @@ jobs:
- name: Build node
if: ${{ (matrix.variant.os != 'ios') && (matrix.variant.os != 'android') }}
run: npm run prebuild:node -- --arch=${{matrix.variant.arch}}
env:
CCACHE_DISABLE: 1

# build the c++ library for IOS
# the Info.plist needs to be regenerated with all libraries in place
25 changes: 19 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
## vNext (TBD)

### Deprecations
* None
## 11.6.0 (2023-03-23)

### Enhancements
* None
* Added configuration option `App.baseFilePath` which controls where synced Realms and metadata is stored.

### Fixed
* Fix type error when using `realm.create` in combination with class base models. (since v11.0.0)

### Compatibility
* React Native >= v0.71.0
* Realm Studio v13.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
<!-- * Either mention core version or upgrade -->
<!-- * Using Realm Core vX.Y.Z -->
<!-- * Upgraded Realm Core from vX.Y.Z to vA.B.C -->
* Test

## 11.5.2 (2023-03-14)

### Fixed
* Suppress omitting `objcMsgsend` stubs to ensure backward compatibility with Xcode 13. It can be observed as `Undefined symbols for architecture arm64: "_objc_msgSend$allBundles", referenced from: realm::copy_bundled_realm_files() in librealm-js-ios.a(platform.o)` when using a React Native app for iOS. ([#5511](https://github.com/realm/realm-js/issues/5511), since v11.5.1)
@@ -24,7 +37,7 @@

### Internal
* Upgraded Realm Core from v13.4.2 to v13.6.0. ([#5495](https://github.com/realm/realm-js/issues/5495))
* All exceptions thrown out of Realm Core are now of type `Exception`.
* All exceptions thrown out of Realm Core are now of type `Exception`.

## 11.5.1-alpha.0 (2023-02-21)

1 change: 1 addition & 0 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@

| Realm JavaScript | React Native | Expo | Hermes | npm | node |
|------------------------|--------------------|----------|--------|--------|--------|
| 11.5.2 | >= 0.71.4 | N/A || >= 7 | >= 13 |
| 11.5.1 | = 0.71.0 | N/A || >= 7 | >= 13 |
| 11.5.0 | = 0.71.0 | N/A || >= 7 | >= 13 |
| 11.4.0 | = 0.71.0 | N/A || >= 7 | >= 13 |
2 changes: 1 addition & 1 deletion dependencies.list
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PACKAGE_NAME=realm-js
VERSION=11.5.1-alpha.0
VERSION=11.6.0
REALM_CORE_VERSION=13.6.0
NAPI_VERSION=5
MDBREALM_TEST_SERVER_TAG=2023-02-23
3 changes: 2 additions & 1 deletion docs/realm.js
Original file line number Diff line number Diff line change
@@ -395,7 +395,8 @@ class Realm {
* Realm database should be stored. For synced Realms, a relative path is used together with app id and
* user id in order to avoid collisions with other apps or users. An absolute path is left untouched
* and on some platforms (iOS and Android) the app might not have permissions to create or open
* the file - permissions are not validated.
* the file - permissions are not validated. If a relative path is specified, it is relative to
* {@link Realm.App~AppConfiguration.baseFilePath}.
* @property {string} [fifoFilesFallbackPath] - Opening a Realm creates a number of FIFO special files in order to
* coordinate access to the Realm across threads and processes. If the Realm file is stored in a location
* that does not allow the creation of FIFO special files (e.g. FAT32 filesystems), then the Realm cannot be opened.
1 change: 1 addition & 0 deletions docs/sync.js
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
* @property {string} id - The id of the Atlas App Services application.
* @property {string} [baseUrl] - The base URL of the Atlas App Services server.
* @property {number} [timeout] - General timeout (in millisecs) for requests.
* @property {string} [baseFilePath] - Specify where synced Realms and metadata is stored. If not specified, the current work directory is used.
* @property {Realm.App~LocalAppConfiguration} [app] - local app configuration
*/

2 changes: 1 addition & 1 deletion example/app/components/TaskManager.tsx
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ export const TaskManager: React.FC<{
// of sync participants to successfully sync everything in the transaction, otherwise
// no changes propagate and the transaction needs to start over when connectivity allows.
realm.write(() => {
return new Task(realm, description, userId);
realm.create(Task, {description, userId});
});
},
[realm, userId],
4 changes: 0 additions & 4 deletions example/app/models/Task.ts
Original file line number Diff line number Diff line change
@@ -19,8 +19,4 @@ export class Task extends Realm.Object<Task> {
userId!: string;

static primaryKey = '_id';

constructor(realm: Realm, description: string, userId?: string) {
super(realm, {description, userId: userId || '_SYNC_DISABLED_'});
}
}
24,513 changes: 12,210 additions & 12,303 deletions example/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
"dependencies": {
"@realm/react": "^0.4.3",
"react": "18.2.0",
"react-native": "0.71.1",
"react-native": "0.71.4",
"react-native-get-random-values": "^1.8.0",
"realm": "*"
},
44 changes: 37 additions & 7 deletions integration-tests/tests/src/node/path.ts
Original file line number Diff line number Diff line change
@@ -20,14 +20,16 @@ import { expect } from "chai";
import Realm, { BSON } from "realm";
import path from "node:path";
import os from "node:os";
import { existsSync, rmSync } from "node:fs";

import { importAppBefore, authenticateUserBefore } from "../hooks";
import { importApp } from "../utils/import-app";

const getAbsolutePath = () => os.tmpdir() + path.sep + new BSON.UUID().toHexString();
const getRelativePath = () => "testFiles" + path.sep + new BSON.UUID().toHexString();
const getPartitionValue = () => new BSON.UUID().toHexString();

const schema = {
const Schema = {
name: "MixedClass",
primaryKey: "_id",
properties: {
@@ -36,24 +38,52 @@ const schema = {
},
};

const FlexibleSchema = { ...Schema, properties: { ...Schema.properties, nonQueryable: "string?" } };

describe("path configuration (local)", function () {
it("relative path", function () {
const filename = getRelativePath();
const realm = new Realm({ path: filename, schema: [schema] });
const realm = new Realm({ path: filename, schema: [Schema] });
expect(realm.path.endsWith(filename)).to.be.true;
realm.close();
Realm.deleteFile({ path: filename });
});

it("absolute path", function () {
const filename = getAbsolutePath();
const realm = new Realm({ path: filename, schema: [schema] });
const realm = new Realm({ path: filename, schema: [Schema] });
expect(realm.path).to.equal(filename);
realm.close();
Realm.deleteFile({ path: filename });
});
});

describe.skipIf(environment.missingServer, `app configuration of root directory (flexible sync)`, async function () {
const { appId, baseUrl } = await importApp("with-db-flx");

it("directory and file created where expected", async function () {
const tmpdir = getAbsolutePath();
expect(fs.exists(tmpdir)).to.be.false;

const app = new Realm.App({ id: appId, baseUrl, baseFilePath: tmpdir });
const user = await app.logIn(Realm.Credentials.anonymous());

const realm = await Realm.open({
schema: [FlexibleSchema],
sync: {
flexible: true,
user,
},
});

expect(existsSync(tmpdir)).to.be.true;
expect(realm.path.startsWith(tmpdir));

realm.close();
rmSync(tmpdir, { recursive: true });
});
});

describe.skipIf(environment.missingServer, "path configuration (partition based sync)", function () {
importAppBefore("with-db");
authenticateUserBefore();
@@ -62,7 +92,7 @@ describe.skipIf(environment.missingServer, "path configuration (partition based
const filename = getAbsolutePath();
const realm = await Realm.open({
path: filename,
schema: [schema],
schema: [Schema],
sync: {
partitionValue: getPartitionValue(),
user: this.user,
@@ -77,7 +107,7 @@ describe.skipIf(environment.missingServer, "path configuration (partition based
const filename = getRelativePath();
const realm = await Realm.open({
path: filename,
schema: [schema],
schema: [Schema],
sync: {
partitionValue: getPartitionValue(),
user: this.user,
@@ -98,7 +128,7 @@ describe.skipIf(environment.skipFlexibleSync, "path configuration (flexible sync
const filename = getAbsolutePath();
const realm = await Realm.open({
path: filename,
schema: [schema],
schema: [FlexibleSchema],
sync: {
flexible: true,
user: this.user,
@@ -114,7 +144,7 @@ describe.skipIf(environment.skipFlexibleSync, "path configuration (flexible sync
const filename = getRelativePath();
const realm = await Realm.open({
path: filename,
schema: [schema],
schema: [FlexibleSchema],
sync: {
flexible: true,
user: this.user,
12 changes: 3 additions & 9 deletions integration-tests/tests/src/tests/sync/app.ts
Original file line number Diff line number Diff line change
@@ -260,29 +260,23 @@ describe("App", () => {

it("MongoDB Realm sync works", async function (this: Mocha.Context & AppContext & RealmContext) {
const dogNames = ["King", "Rex"]; // must be sorted
let nCalls = 0;

const partitionValue = generatePartition();
const realmConfig: Realm.Configuration = {
schema: [PersonForSyncSchema, DogForSyncSchema],
shouldCompact: () => {
nCalls++;
return true;
},
sync: {
user: this.user,
partitionValue,
//@ts-expect-error TYPEBUG: cannot access const enum at runtime
_sessionStopPolicy: "immediately", // Make it safe to delete files after realm.close()
},
};

Realm.deleteFile(realmConfig);
const realm = await Realm.open(realmConfig);
expect(nCalls).equals(1);
realm.write(() => {
const tmpDogs: IDogForSyncSchema[] = [];
dogNames.forEach((n) => {
console.log("FISK 4", n);
const dog = realm.create<IDogForSyncSchema>(DogForSyncSchema.name, { _id: new BSON.ObjectId(), name: n });
tmpDogs.push(dog);
return tmpDogs;
@@ -296,14 +290,14 @@ describe("App", () => {
});
});

const realmPath = realm.path;
await realm.syncSession?.uploadAllLocalChanges();
expect(realm.objects("Dog").length).equals(2);
realm.close();

Realm.deleteFile(realmConfig);
Realm.deleteFile({ path: realmPath });

const realm2 = await Realm.open(realmConfig);
expect(nCalls).equals(2);
await realm2.syncSession?.downloadAllServerChanges();

const dogs = realm2.objects<IDogForSyncSchema>(DogForSyncSchema.name).sorted("name");
4 changes: 2 additions & 2 deletions package-lock.json
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "realm",
"description": "Realm is a mobile database: an alternative to SQLite and key-value stores",
"version": "11.5.1",
"version": "11.6.0",
"license": "apache-2.0",
"homepage": "https://realm.io",
"keywords": [
4 changes: 2 additions & 2 deletions react-native/ios/RealmReact.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -191,7 +191,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 11.5.1;
CURRENT_PROJECT_VERSION = 11.6.0;
CXX = "$(SRCROOT)/../../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -255,7 +255,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 11.5.1;
CURRENT_PROJECT_VERSION = 11.6.0;
CXX = "$(SRCROOT)/../../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
21 changes: 14 additions & 7 deletions src/js_app.hpp
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
#include "js_network_transport.hpp"
#include "js_email_password_auth.hpp"
#include "realm/object-store/sync/subscribable.hpp"
#include "realm/util/file.hpp"


using SharedApp = std::shared_ptr<realm::app::App>;
@@ -170,6 +171,7 @@ void AppClass<T>::constructor(ContextType ctx, ObjectType this_object, Arguments
static const String config_app = "app";
static const String config_app_name = "name";
static const String config_app_version = "version";
static const String config_base_file_path = "baseFilePath";

args.validate_count(1);

@@ -178,6 +180,11 @@ void AppClass<T>::constructor(ContextType ctx, ObjectType this_object, Arguments
std::string id;
realm::app::App::Config config;

SyncClientConfig client_config;
client_config.metadata_mode = SyncManager::MetadataMode::NoEncryption;
client_config.user_agent_binding_info = get_user_agent();
client_config.base_file_path = default_realm_file_directory(); // this may be changed

if (Value::is_object(ctx, args[0])) {
ObjectType config_object = Value::validated_to_object(ctx, args[0]);

@@ -217,6 +224,11 @@ void AppClass<T>::constructor(ContextType ctx, ObjectType this_object, Arguments
std::optional<std::string>(Value::validated_to_string(ctx, config_app_version_value, "version"));
}
}

ValueType base_file_path_value = Object::get_property(ctx, config_object, config_base_file_path);
if (!Value::is_undefined(ctx, base_file_path_value)) {
client_config.base_file_path = Value::validated_to_string(ctx, base_file_path_value);
}
}
else if (Value::is_string(ctx, args[0])) {
config.app_id = Value::validated_to_string(ctx, args[0]);
@@ -238,13 +250,8 @@ void AppClass<T>::constructor(ContextType ctx, ObjectType this_object, Arguments
config.device_info.framework_name = framework_name;
config.device_info.framework_version = framework_version;

auto realm_file_directory = default_realm_file_directory();
ensure_directory_exists_for_file(realm_file_directory);

SyncClientConfig client_config;
client_config.base_file_path = realm_file_directory;
client_config.metadata_mode = SyncManager::MetadataMode::NoEncryption;
client_config.user_agent_binding_info = get_user_agent();
util::try_make_dir(client_config.base_file_path);
set_default_realm_file_directory(client_config.base_file_path);

SharedApp app = app::App::get_shared_app(config, client_config);

12 changes: 12 additions & 0 deletions src/node/platform.cpp
Original file line number Diff line number Diff line change
@@ -24,6 +24,8 @@

#include "../platform.hpp"

static std::string s_default_realm_directory;

namespace realm {

class UVException : public std::runtime_error {
@@ -44,9 +46,19 @@ struct FileSystemRequest : uv_fs_t {
}
};

void set_default_realm_file_directory(std::string dir)
{
s_default_realm_directory = dir;
}

// taken from Node.js: function Cwd in node.cc
std::string default_realm_file_directory()
{

if (!s_default_realm_directory.empty()) {
return s_default_realm_directory;
}

#ifdef _WIN32
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
char buf[MAX_PATH * 4];
5 changes: 5 additions & 0 deletions types/app.d.ts
Original file line number Diff line number Diff line change
@@ -355,6 +355,11 @@ declare namespace Realm {
*/
baseUrl?: string;

/**
* An optional path to a directory where synced Realms are stored.
*/
baseFilePath?: string;

/**
* This describes the local app, sent to the server when a user authenticates.
* Specifying this will enable the server to respond differently to specific versions of specific apps.
4 changes: 2 additions & 2 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1293,8 +1293,8 @@ declare class Realm {
* @param {Realm.UpdateMode} mode? If not provided, `Realm.UpdateMode.Never` is used.
* @returns T
*/
create<T extends Realm.Object>(type: {new(...arg: any[]): T; }, properties: Unmanaged<T>, mode?: Realm.UpdateMode.Never): T;
create<T extends Realm.Object>(type: {new(...arg: any[]): T; }, properties: Partial<T> | Partial<Unmanaged<T>>, mode: Realm.UpdateMode.All | Realm.UpdateMode.Modified): T;
create<T extends Realm.Object<any>>(type: {new(...arg: any[]): T; }, properties: Unmanaged<T>, mode?: Realm.UpdateMode.Never): T;
create<T extends Realm.Object<any>>(type: {new(...arg: any[]): T; }, properties: Partial<T> | Partial<Unmanaged<T>>, mode: Realm.UpdateMode.All | Realm.UpdateMode.Modified): T;

/**
* @param {Realm.Object|Realm.Object[]|Realm.List<any>|Realm.Results<any>|any} object