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

Application class #446

Merged
merged 42 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
453e018
Rollback Dart_WeakHandle finalizer hack
nielsenko Mar 14, 2022
8430d42
Use dart main/flutter beta in github actions.
nielsenko Mar 22, 2022
e847de2
Add dart specific support for realm_http_transport_new
nielsenko Mar 16, 2022
6a5c9c4
Wire up realm_core
nielsenko Mar 18, 2022
fca9182
Apply suggestions from code review
nielsenko Mar 28, 2022
435e484
Copy all info from realm_http_request before starting async request
nielsenko Mar 28, 2022
d7207d9
Added ApplicationConfiguration
nielsenko Mar 18, 2022
ea8d7ef
Added Application class with async logIn method (includes stubs for U…
nielsenko Mar 25, 2022
a54b1a8
Use common GCHandle class for userdata on all callbacks
nielsenko Mar 30, 2022
6ae70e2
Support hard gc handles as well, as suggested by Yavor. Ie. handles t…
nielsenko Apr 7, 2022
c81e0c0
Backport to dart 2.16 where we have to work around a finalization iss…
nielsenko Apr 1, 2022
6899dc8
Add support for http_transport
nielsenko Mar 18, 2022
9a17d45
Added ApplicationConfiguration
nielsenko Mar 18, 2022
73e2e4c
Update docs on public interface
nielsenko Apr 7, 2022
0baa62f
Address PR feedback
nielsenko Apr 11, 2022
20e95af
Added Application class with async logIn method (includes stubs for U…
nielsenko Apr 8, 2022
d63f205
Add testWithBass function
nielsenko Apr 8, 2022
0cdf4b7
Merge branch 'master' into realm_app_config
desistefanova Apr 11, 2022
b9cc163
Update CHANGELOG.md
desistefanova Apr 11, 2022
8448ffd
Merge branch 'realm_app_config' into realm_app
desistefanova Apr 11, 2022
7ff02ef
Commit after merge
desistefanova Apr 11, 2022
fc5e481
Fixes after merge
desistefanova Apr 11, 2022
c1cb35e
Merge branch 'realm_app'
desistefanova Apr 12, 2022
e07be97
Fixes after merge
desistefanova Apr 12, 2022
b7ddc96
Remove user and login
desistefanova Apr 12, 2022
938a168
size of handles
desistefanova Apr 12, 2022
ef644c5
workflow chanel = stable
desistefanova Apr 12, 2022
a132bf4
Delete realm_dart_http_transport
desistefanova Apr 12, 2022
4e15ea7
remove import dart:async from tests
desistefanova Apr 12, 2022
c453fde
Merge branch 'master' into realm_app
desistefanova Apr 12, 2022
348ed3e
Fixes after merge
desistefanova Apr 12, 2022
2778ff2
Fix after merge
desistefanova Apr 12, 2022
a359038
Merge branch 'master' into realm_app
desistefanova Apr 12, 2022
1489eee
Merge branch 'master' into realm_app
desistefanova Apr 12, 2022
9fd8fec
Fix after merge
desistefanova Apr 12, 2022
07be0ae
Fix after merge
desistefanova Apr 12, 2022
8c213f9
fixup application
blagoev Apr 12, 2022
a673a91
change default application dir
blagoev Apr 12, 2022
96324de
trigger actions
blagoev Apr 12, 2022
5b63103
trigger
blagoev Apr 12, 2022
7f00a6c
fix application config and app tests
blagoev Apr 12, 2022
e857860
change filesPath to current dir
blagoev Apr 12, 2022
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ out
# Ignore realm files
lib/default.realm
lib/default.realm.lock
mongodb-realm/

# Dart packages and Flutter plugins should not commit these files
pubspec.lock
Expand Down Expand Up @@ -35,4 +36,4 @@ flutter/realm_flutter/.gradle/

# Ignore example pubspec.lock since the example always reference the local package
example/pubspec.lock
/generator/coverage/
/generator/coverage/
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ x.x.x Release notes (yyyy-MM-dd)

### Enhancements
* Added a property `Configuration.disableFormatUpgrade`. When set to `true`, opening a Realm with an older file format will throw an exception to avoid automatically upgrading it. ([#310](https://github.com/realm/realm-dart/pull/310))
* Support result value from write transaction callbacks ([#294](https://github.com/realm/realm-dart/pull/294/))
* Support result value from write transaction callbacks. ([#294](https://github.com/realm/realm-dart/pull/294/))
* Added a property `Realm.isInTransaction` that indicates whether the Realm instance has an open write transaction associated with it.
* Support anonymous application credentials ([#443](https://github.com/realm/realm-dart/pull/443/))
* Support anonymous application credentials. ([#443](https://github.com/realm/realm-dart/pull/443/))
* Added a property `Configuration.initialDataCallback`. This is a callback executed when a Realm file is first created and allows you to populate some initial data necessary for your application. ([#298](https://github.com/realm/realm-dart/issues/298))
* Support application configuration ([#306](https://github.com/realm/realm-dart/pull/306/))
* Support application configuration. ([#306](https://github.com/realm/realm-dart/pull/306/))
* Support application class. ([#446](https://github.com/realm/realm-dart/pull/446/))
* Support should realm compact on open callback `Configuration.shouldCompactCallback` as option when configuring a Realm to determine if it should be compacted before being returned. ([#466](https://github.com/realm/realm-dart/pull/466/))
* Support ObjectId ([#468](https://github.com/realm/realm-dart/pull/468))
* Support ObjectId. ([#468](https://github.com/realm/realm-dart/pull/468))

### Fixed
* Fixed an issue that would result in the wrong transaction being rolled back if you start a write transaction inside a write transaction. ([#442](https://github.com/realm/realm-dart/issues/442))
Expand Down
2 changes: 2 additions & 0 deletions flutter/realm_flutter/ios/Classes/RealmPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ void dummy(void) {
realm_results_get_object(NULL, 0);
realm_list_size(NULL, 0);
realm_results_snapshot(NULL);
realm_http_transport_new(NULL, NULL, NULL);
realm_config_set_should_compact_on_launch_function(NULL, NULL, NULL);
realm_app_credentials_new_anonymous();
realm_app_config_new(NULL, NULL);
realm_sync_client_config_new();
}

@end
6 changes: 4 additions & 2 deletions flutter/realm_flutter/tests/test_driver/realm_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import '../test/realm_test.dart' as realm_tests;
import '../test/realm_object_test.dart' as realm_object_tests;
import '../test/list_test.dart' as list_tests;
import '../test/results_test.dart' as results_tests;
import '../test/credentials_test.dart' as credentials;
import '../test/credentials_test.dart' as credentials_tests;
import '../test/application_test.dart' as application_tests;

Future<String> main(List<String> args) async {
final Completer<String> completer = Completer<String>();
Expand All @@ -22,7 +23,8 @@ Future<String> main(List<String> args) async {
await realm_object_tests.main(args);
await list_tests.main(args);
await results_tests.main(args);
await credentials.main(args);
await credentials_tests.main(args);
await application_tests.main(args);

tearDown(() {
if (Invoker.current?.liveTest.state.result == test_api.Result.error || Invoker.current?.liveTest.state.result == test_api.Result.failure) {
Expand Down
26 changes: 23 additions & 3 deletions lib/src/application.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@

import 'dart:io';
import 'package:meta/meta.dart';
import 'native/realm_core.dart';
import 'configuration.dart';

/// Specify if and how to persists user objects.
enum MetadataPersistenceMode {
/// Persist [User] objects, but do not encrypt them.
unencrypted,
plaintext,

/// Persist [User] objects in an encrypted store.
encrypted,
Expand All @@ -32,6 +34,8 @@ enum MetadataPersistenceMode {
}

@immutable

/// A class exposing configuration options for an [Application]
class ApplicationConfiguration {
/// The [appId] is the unique id that identifies the Realm application.
final String appId;
Expand Down Expand Up @@ -91,10 +95,26 @@ class ApplicationConfiguration {
this.defaultRequestTimeout = const Duration(seconds: 60),
this.localAppName,
this.localAppVersion,
this.metadataPersistenceMode = MetadataPersistenceMode.unencrypted,
this.metadataEncryptionKey,
this.metadataPersistenceMode = MetadataPersistenceMode.plaintext,
HttpClient? httpClient,
}) : baseUrl = baseUrl ?? Uri.parse('https://realm.mongodb.com'),
baseFilePath = baseFilePath ?? Directory.current,
baseFilePath = baseFilePath ?? Directory(Configuration.filesPath),
httpClient = httpClient ?? HttpClient();
}

/// An [Application] is the main client-side entry point for interacting with a MongoDB Realm App.
///
/// The [Application]] can be used to
/// * Register uses and perform various user-related operations through authentication providers
/// * Synchronize data between the local device and a remote Realm App with Synchronized Realms
class Application {
final AppHandle _handle;
final ApplicationConfiguration configuration;

Application(this.configuration) : _handle = realmCore.getApp(configuration);
}

extension ApplicationInternal on Application {
AppHandle get handle => _handle;
}
2 changes: 1 addition & 1 deletion lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Configuration {
if (Platform.isAndroid || Platform.isIOS) {
return realmCore.getFilesPath();
}
return "";
return Directory.current.absolute.path;
}

/// The schema version used to open the [Realm]
Expand Down
39 changes: 38 additions & 1 deletion lib/src/native/realm_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

// ignore_for_file: constant_identifier_names, non_constant_identifier_names

import 'dart:async';
import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
Expand All @@ -27,6 +28,7 @@ import 'dart:typed_data';
import 'package:ffi/ffi.dart' hide StringUtf8Pointer, StringUtf16Pointer;

import '../application.dart';
import '../credentials.dart';
import '../collections.dart';
import '../init.dart';
import '../list.dart';
Expand Down Expand Up @@ -825,6 +827,29 @@ class _RealmCore {
}
});
}

SyncClientConfigHandle createSyncClientConfig(ApplicationConfiguration configuration) {
return using((arena) {
final handle = SyncClientConfigHandle._(_realmLib.realm_sync_client_config_new());

_realmLib.realm_sync_client_config_set_base_file_path(handle._pointer, configuration.baseFilePath.path.toUtf8Ptr(arena));
_realmLib.realm_sync_client_config_set_metadata_mode(handle._pointer, configuration.metadataPersistenceMode.index);

if (configuration.metadataEncryptionKey != null && configuration.metadataPersistenceMode == MetadataPersistenceMode.encrypted) {
_realmLib.realm_sync_client_config_set_metadata_encryption_key(handle._pointer, configuration.metadataEncryptionKey!.toUint8Ptr(arena));
}

return handle;
});
}

AppHandle getApp(ApplicationConfiguration configuration) {
final httpTransport = createHttpTransport(configuration.httpClient);
final appConfig = createAppConfig(configuration, httpTransport);
final syncClientConfig = createSyncClientConfig(configuration);
final realm_app = _realmLib.invokeGetPointer(() => _realmLib.realm_app_get(appConfig._pointer, syncClientConfig._pointer));
return AppHandle._(realm_app);
}
}

class LastError {
Expand Down Expand Up @@ -930,11 +955,23 @@ class RealmHttpTransportHandle extends Handle<realm_http_transport> {
}

class AppConfigHandle extends Handle<realm_app_config> {
AppConfigHandle._(Pointer<realm_app_config> pointer) : super(pointer, 256); // TODO: What should hint be?
AppConfigHandle._(Pointer<realm_app_config> pointer) : super(pointer, 8);
}

class SyncClientConfigHandle extends Handle<realm_sync_client_config> {
SyncClientConfigHandle._(Pointer<realm_sync_client_config> pointer) : super(pointer, 8);
}

class AppHandle extends Handle<realm_app> {
AppHandle._(Pointer<realm_app> pointer) : super(pointer, 16);
}

extension on List<int> {
Pointer<Int8> toInt8Ptr(Allocator allocator) {
return toUint8Ptr(allocator).cast();
}

Pointer<Uint8> toUint8Ptr(Allocator allocator) {
final nativeSize = length + 1;
final result = allocator<Uint8>(nativeSize);
final Uint8List native = result.asTypedList(nativeSize);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/realm_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import 'realm_object.dart';
import 'results.dart';

// always expose with `show` to explicitly control the public API surface
export 'application.dart' show ApplicationConfiguration, MetadataPersistenceMode;
export 'application.dart' show ApplicationConfiguration, MetadataPersistenceMode, Application;
export 'package:realm_common/realm_common.dart'
show Ignored, Indexed, MapTo, PrimaryKey, RealmError, RealmModel, RealmUnsupportedSetError, RealmStateError, RealmCollectionType, RealmPropertyType, ObjectId;
export "configuration.dart" show Configuration, RealmSchema, SchemaObject;
Expand Down
1 change: 1 addition & 0 deletions src/realm_dart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ void dummy(void) {
realm_results_snapshot(nullptr);
realm_config_set_should_compact_on_launch_function(nullptr, nullptr, nullptr);
realm_app_config_new(nullptr, nullptr);
realm_sync_client_config_new();
realm_app_credentials_new_anonymous();
realm_http_transport_new(nullptr, nullptr, nullptr);
#if (ANDROID)
Expand Down
9 changes: 8 additions & 1 deletion test/application_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Future<void> main([List<String>? args]) async {
test('ApplicationConfiguration can be created', () {
final a = ApplicationConfiguration('myapp');
expect(a.appId, 'myapp');
expect(a.baseFilePath.path, Directory.current.path);
expect(a.baseFilePath.path, Configuration.filesPath);
expect(a.baseUrl, Uri.parse('https://realm.mongodb.com'));
expect(a.defaultRequestTimeout, const Duration(minutes: 1));

Expand All @@ -51,4 +51,11 @@ Future<void> main([List<String>? args]) async {
expect(b.defaultRequestTimeout, const Duration(seconds: 2));
expect(b.httpClient, httpClient);
});

test('Application can be created', () async {

final configuration = ApplicationConfiguration(generateRandomString(10));
final application = Application(configuration);
expect(application.configuration, configuration);
});
}
6 changes: 3 additions & 3 deletions test/configuration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ Future<void> main([List<String>? args]) async {

test('Configuration files path', () {
if (Platform.isAndroid || Platform.isIOS) {
expect(Configuration.filesPath, isNot(endsWith(".realm")), reason: "on Android and iOS the files path should be a directory");
expect(Configuration.filesPath, startsWith("/"), reason: "on Android and iOS the files path should be a directory");
expect(Configuration.filesPath, isNot(endsWith(".realm")), reason: "on Android and iOS the filesPath should be a directory");
expect(Configuration.filesPath, startsWith("/"), reason: "on Android and iOS the filesPath should be a directory");
} else {
expect(Configuration.filesPath, equals(""), reason: "on Dart standalone the files path should be an empty string");
expect(Configuration.filesPath, equals(Directory.current.absolute.path), reason: "on Dart standalone the filesPath should be the current dir path");
}
});

Expand Down
4 changes: 2 additions & 2 deletions test/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ String generateRandomRealmPath() {
if (Platform.isAndroid || Platform.isIOS) {
path = _path.join(Configuration.filesPath, path);
} else {
path = _path.join(Directory.systemTemp.createTempSync("rt_").path, path);
path = _path.join(Directory.systemTemp.createTempSync("realm_test_").path, path);
}

return path;
Expand Down Expand Up @@ -194,4 +194,4 @@ Future<void> setupBaas() async {
final client = await (cluster == null ? BaasClient.docker(baasUrl) : BaasClient.atlas(baasUrl, cluster, apiKey!, privateApiKey!, projectId!));

baasApps.addAll(await client.getOrCreateApps());
}
}