diff --git a/CHANGELOG.md b/CHANGELOG.md index f3619725..5156483e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +x.x.x Release notes (yyyy-MM-dd) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* Configuration of sync file system is not done on module import but later when actually needed by sync (#1351) + + 2.0.0 Release notes (2017-9-28) ============================================================= ### Breaking changes @@ -25,6 +37,9 @@ * Alignment of permission schemas. * Updating sync (2.0.0-rc24). + + + 2.0.0-rc10 Release notes (2017-9-19) ============================================================= ### Breaking changes diff --git a/docs/sync.js b/docs/sync.js index 3b271d5a..09ffc302 100644 --- a/docs/sync.js +++ b/docs/sync.js @@ -135,7 +135,7 @@ class User { * @param {function(error, user)} [callback] - called with the following arguments: * - `error` - an Error object is provided on failure * - `user` - a valid User object on success - * @returns {void|Promise} Returns a promise with a user if the callback was not specified + * @returns {void|Promise} Returns a promise with a user if the callback was not specified */ static login(server, username, password, callback) {} @@ -149,7 +149,7 @@ class User { * @param {function(error, User)} [callback] - an optional callback called with the following arguments: * - `error` - an Error object is provided on failure * - `user` - a valid User object on success - * @return {void|Promise} Returns a promise with a user if the callback was not specified + * @return {void|Promise} Returns a promise with a user if the callback was not specified */ static registerWithProvider(server, options, callback) {} @@ -161,7 +161,7 @@ class User { * @param {function(error, user)} [callback] - called with the following arguments: * - `error` - an Error object is provided on failure * - `user` - a valid User object on success - * @return {void|Promise} Returns a promise with a user if the callback was not specified + * @return {void|Promise} Returns a promise with a user if the callback was not specified */ static register(server, username, password, callback) {} @@ -248,7 +248,7 @@ class User { * @param {string} recipient the optional recipient of the permission. Can be either * 'any' which is the default, or 'currentUser' or 'otherUser' if you want only permissions * belonging to the user or *not* belonging to the user. - * @returns {Results} a queryable collection of permission objects that provides detailed + * @returns {Results} a queryable collection of permission objects that provides detailed * information regarding the granted access. * The collection is a live query similar to what you would get by callig Realm.objects, * so the same features apply - you can listen for notifications or filter it. @@ -261,22 +261,22 @@ class User { * This should be an object, containing either the key 'userId', or 'metadataKey' and 'metadataValue'. * @param {string} realmUrl - The path to the Realm that you want to apply permissions to. * @param {string} accessLevel - The access level you want to set: 'none', 'read', 'write' or 'admin'. - * @returns {Promise} a Promise that, upon completion, indicates that the permissions have been - * successfully applied by the server. It will be resolved with the + * @returns {Promise} a Promise that, upon completion, indicates that the permissions have been + * successfully applied by the server. It will be resolved with the * {@link PermissionChange PermissionChange} object that refers to the applied permission. */ applyPermissions(condition, realmUrl, accessLevel) { } /** * Generates a token that can be used for sharing a Realm. - * @param {string} realmUrl - The Realm URL whose permissions settings should be changed. Use * to change + * @param {string} realmUrl - The Realm URL whose permissions settings should be changed. Use * to change * the permissions of all Realms managed by this user. - * @param {string} accessLevel - The access level to grant matching users. Note that the access level - * setting is additive, i.e. you cannot revoke permissions for users who previously had a higher access level. + * @param {string} accessLevel - The access level to grant matching users. Note that the access level + * setting is additive, i.e. you cannot revoke permissions for users who previously had a higher access level. * Can be 'read', 'write' or 'admin'. * @param {Date} [expiresAt] - Optional expiration date of the offer. If set to null, the offer doesn't expire. * @returns {string} - A token that can be shared with another user, e.g. via email or message and then consumed by - * User.acceptPermissionOffer to obtain permissions to a Realm. + * User.acceptPermissionOffer to obtain permissions to a Realm. */ offerPermissions(realmUrl, accessLevel, expiresAt) { } @@ -291,9 +291,9 @@ class User { * Invalidates a permission offer. * Invalidating an offer prevents new users from consuming its token. It doesn't revoke any permissions that have * already been granted. - * @param {string|PermissionOffer} permissionOfferOrToken - Either the token or the entire - * {@link PermissionOffer PermissionOffer} object that was generated with - * {@link Realm#Sync#User#offerPermissions offerPermissions}. + * @param {string|PermissionOffer} permissionOfferOrToken - Either the token or the entire + * {@link PermissionOffer PermissionOffer} object that was generated with + * {@link Realm#Sync#User#offerPermissions offerPermissions}. */ invalidatePermissionOffer(permissionOfferOrToken) { } } @@ -338,7 +338,7 @@ class Session { /** * Register a progress notification callback on a session object * @param {string} direction - The progress direction to register for. - * Can be either: + * Can be either: * - `download` - report download progress * - `upload` - report upload progress * @param {string} mode - The progress notification mode to use for the registration. @@ -405,12 +405,12 @@ class Adapter { } /** - * The following Instructions can be returned by `Adapter.current(path)`. Each instruction object has + * The following Instructions can be returned by `Adapter.current(path)`. Each instruction object has * a `type` property which is one of the following types. For each type below we list the other properties * that will exist in the instruction object. * @typedef Realm.Sync.Adapter~Instruction * @type {(INSERT|SET|DELETE|CLEAR|CHANGE_IDENTITY|LIST_SET|LIST_INSERT|LIST_ERASE|LIST_CLEAR|ADD_TYPE|ADD_PROPERTY)} - * @property INSERT - insert a new object + * @property INSERT - insert a new object * - `object_type` - type of the object being inserted * - `identity` - primary key value or row index for the object * - `values` - map of property names and property values for the object to insert @@ -423,7 +423,7 @@ class Adapter { * - `identity` - primary key value or row index for the object * @property CLEAR - delete all objects of a given type * - `object_type` - type of the object - * @property LIST_SET - set the object at a given list index to an object + * @property LIST_SET - set the object at a given list index to an object * - `object_type` - type of the object * - `identity` - primary key for the object * - `property` - property name for the list property to mutate diff --git a/lib/index.d.ts b/lib/index.d.ts index 76106fe4..06637d21 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -288,7 +288,7 @@ declare namespace Realm.Sync { openManagementRealm(): Realm; retrieveAccount(provider: string, username: string): Promise; - getGrantedPermissions(recipient: 'any' | 'currentUser' | 'otherUser'): Results; + getGrantedPermissions(recipient: 'any' | 'currentUser' | 'otherUser'): Results; applyPermissions(condition: PermissionCondition, realmUrl: string, accessLevel: AccessLevel): Promise; offerPermissions(realmUrl: string, accessLevel: AccessLevel, expiresAt?: Date): Promise; acceptPermissionOffer(token: string): Promise @@ -296,49 +296,49 @@ declare namespace Realm.Sync { } type PermissionCondition = { - userId: string | - { metadataKey: string, metadataValue: string } + userId: string | + { metadataKey: string, metadataValue: string } }; - type AccessLevel = 'none' | 'read' | 'write' | 'admin'; + type AccessLevel = 'none' | 'read' | 'write' | 'admin'; class Permission { - readonly id: string; - readonly updatedAt: Date; - readonly userId: string; - readonly path: string; - readonly mayRead?: boolean; - readonly mayWrite?: boolean; - readonly mayManage?: boolean; + readonly id: string; + readonly updatedAt: Date; + readonly userId: string; + readonly path: string; + readonly mayRead?: boolean; + readonly mayWrite?: boolean; + readonly mayManage?: boolean; } class PermissionChange { - id: string; - createdAt: Date; - updatedAt: Date; - statusCode?: number; - statusMessage?: string; - userId: string; - metadataKey?: string; - metadataValue?: string; - realmUrl: string; - mayRead?: boolean; - mayWrite?: boolean; - mayManage?: boolean; + id: string; + createdAt: Date; + updatedAt: Date; + statusCode?: number; + statusMessage?: string; + userId: string; + metadataKey?: string; + metadataValue?: string; + realmUrl: string; + mayRead?: boolean; + mayWrite?: boolean; + mayManage?: boolean; } class PermissionOffer { - id: string; - createdAt: Date; - updatedAt: Date; - statusCode?: number; - statusMessage?: string; - token?: string; - realmUrl: string; - mayRead?: boolean; - mayWrite?: boolean; - mayManage?: boolean; - expiresAt?: Date; + id: string; + createdAt: Date; + updatedAt: Date; + statusCode?: number; + statusMessage?: string; + token?: string; + realmUrl: string; + mayRead?: boolean; + mayWrite?: boolean; + mayManage?: boolean; + expiresAt?: Date; } type ErrorCallback = (message?: string, isFatal?: boolean, category?: string, code?: number) => void; @@ -436,8 +436,8 @@ declare namespace Realm.Sync { } -interface ProgressPromise extends Promise { - progress(callback: Realm.Sync.ProgressNotificationCallback) : Promise +interface ProgressPromise extends Promise { + progress(callback: Realm.Sync.ProgressNotificationCallback): Promise } declare class Realm { diff --git a/src/js_sync.hpp b/src/js_sync.hpp index 5d7c1d72..f8f30ace 100644 --- a/src/js_sync.hpp +++ b/src/js_sync.hpp @@ -39,6 +39,15 @@ namespace realm { namespace js { +inline realm::SyncManager& syncManagerShared() { + static bool configured = []{ + ensure_directory_exists_for_file(default_realm_file_directory()); + SyncManager::shared().configure_file_system(default_realm_file_directory(), SyncManager::MetadataMode::NoEncryption); + return true; + }(); + return SyncManager::shared(); +} + using SharedUser = std::shared_ptr; using WeakSession = std::weak_ptr; @@ -127,7 +136,7 @@ void UserClass::create_user(ContextType ctx, FunctionType, ObjectType this_ob Value::validated_to_string(ctx, arguments[1], "identity"), Value::validated_to_string(ctx, arguments[0], "authServerUrl") }; - SharedUser *user = new SharedUser(SyncManager::shared().get_user( + SharedUser *user = new SharedUser(syncManagerShared().get_user( userIdentifier, Value::validated_to_string(ctx, arguments[2], "refreshToken") )); @@ -141,7 +150,7 @@ void UserClass::create_user(ContextType ctx, FunctionType, ObjectType this_ob template void UserClass::admin_user(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { validate_argument_count(argc, 2, 2); - SharedUser *user = new SharedUser(SyncManager::shared().get_admin_token_user( + SharedUser *user = new SharedUser(syncManagerShared().get_admin_token_user( Value::validated_to_string(ctx, arguments[0], "authServerUrl"), Value::validated_to_string(ctx, arguments[1], "refreshToken") )); @@ -151,7 +160,7 @@ void UserClass::admin_user(ContextType ctx, FunctionType, ObjectType this_obj template void UserClass::all_users(ContextType ctx, ObjectType object, ReturnValue &return_value) { auto users = Object::create_empty(ctx); - for (auto user : SyncManager::shared().all_logged_in_users()) { + for (auto user : syncManagerShared().all_logged_in_users()) { if (user->token_type() == SyncUser::TokenType::Normal) { Object::set_property(ctx, users, user->identity(), create_object>(ctx, new SharedUser(user)), ReadOnly | DontDelete); } @@ -537,10 +546,6 @@ inline typename T::Function SyncClass::create_constructor(ContextType ctx) { Object::set_property(ctx, sync_constructor, "User", ObjectWrap>::create_constructor(ctx), attributes); Object::set_property(ctx, sync_constructor, "Session", ObjectWrap>::create_constructor(ctx), attributes); - // setup synced realmFile paths - ensure_directory_exists_for_file(default_realm_file_directory()); - SyncManager::shared().configure_file_system(default_realm_file_directory(), SyncManager::MetadataMode::NoEncryption); - return sync_constructor; } @@ -555,7 +560,7 @@ void SyncClass::set_sync_log_level(ContextType ctx, FunctionType, ObjectType in >> log_level_2; // Throws if (!in || !in.eof()) throw std::runtime_error("Bad log level"); - realm::SyncManager::shared().set_log_level(log_level_2); + syncManagerShared().set_log_level(log_level_2); } template @@ -639,7 +644,7 @@ void SyncClass::populate_sync_config(ContextType ctx, ObjectType realm_constr config.schema_mode = SchemaMode::Additive; - config.path = realm::SyncManager::shared().path_for_realm(*shared_user, raw_realm_url); + config.path = syncManagerShared().path_for_realm(*shared_user, raw_realm_url); if (!config.encryption_key.empty()) { config.sync_config->realm_encryption_key = std::array(); diff --git a/tests/js/download-api-helper.js b/tests/js/download-api-helper.js index 5b9e6c4b..fd899431 100644 --- a/tests/js/download-api-helper.js +++ b/tests/js/download-api-helper.js @@ -11,9 +11,9 @@ var Realm = require(realmModule); function createObjects(user) { const config = { - sync: { user, - url: `realm://localhost:9080/~/${realmName}`, - error: err => console.log(err) + sync: { user, + url: `realm://localhost:9080/~/${realmName}`, + error: err => console.log(err) }, schema: [{ name: 'Dog', properties: { name: 'string' } }] }; @@ -43,8 +43,8 @@ Realm.Sync.User.register('http://localhost:9080', username, 'password', (error, createObjects(loggedUser); } }); - } - else { + } + else { createObjects(registeredUser); } -}); \ No newline at end of file +}); diff --git a/tests/js/index.js b/tests/js/index.js index 98016926..40b9af42 100644 --- a/tests/js/index.js +++ b/tests/js/index.js @@ -46,7 +46,6 @@ if (global.enableSyncTests) { // FIXME: Permission tests currently fail in chrome debugging mode. if (typeof navigator === 'undefined' || !/Chrome/.test(navigator.userAgent)) { // eslint-disable-line no-undef - //TESTS.PermissionTests = require('./permission-tests'); } } diff --git a/tests/js/session-tests.js b/tests/js/session-tests.js index 7087d027..36b52840 100644 --- a/tests/js/session-tests.js +++ b/tests/js/session-tests.js @@ -29,7 +29,7 @@ const isNodeProccess = (typeof process === 'object' && process + '' === '[object function node_require(module) { return require(module); -} +} let tmp; let fs; @@ -275,7 +275,7 @@ module.exports = { }); }); }, - + testProgressNotificationsForRealmOpenAsync() { if (!isNodeProccess) { return Promise.resolve(); @@ -292,7 +292,7 @@ module.exports = { let progressNotificationCalled = false; let config = { sync: { user, url: `realm://localhost:9080/~/${realmName}`, - _onDownloadProgress: (transferred, total) => { + _onDownloadProgress: (transferred, total) => { progressNotificationCalled = true }, }, @@ -486,7 +486,7 @@ module.exports = { const progressCallback = (transferred, total) => { resolve(); }; - + realm.syncSession.addProgressNotification('download', 'reportIndefinitely', progressCallback); setTimeout(function() { @@ -495,7 +495,7 @@ module.exports = { }); }); }); - }, + }, testProgressNotificationsUnregisterForRealmConstructor() { if (!isNodeProccess) { @@ -519,7 +519,7 @@ module.exports = { let realm = new Realm(config); let unregisterFunc; - + let writeDataFunc = () => { realm.write(() => { for (let i = 1; i <= 3; i++) { @@ -534,14 +534,14 @@ module.exports = { if (failOnCall) { reject(new Error("Progress callback should not be called after removeProgressNotification")); } - + syncFinished = transferred === total; - + //unregister and write some new data. - if (syncFinished) { + if (syncFinished) { failOnCall = true; unregisterFunc(); - + //use second callback to wait for sync finished realm.syncSession.addProgressNotification('upload', 'reportIndefinitely', (x, y) => { if (x === y) { @@ -551,9 +551,9 @@ module.exports = { writeDataFunc(); } }; - + realm.syncSession.addProgressNotification('upload', 'reportIndefinitely', progressCallback); - + unregisterFunc = () => { realm.syncSession.removeProgressNotification(progressCallback); }; @@ -601,7 +601,7 @@ module.exports = { }); }); }); - }, + }, testProgressNotificationsForRealmOpenAsync2() { if (!isNodeProccess) { @@ -624,14 +624,14 @@ module.exports = { }; let progressCalled = false; - - Realm.openAsync(config, + + Realm.openAsync(config, (error, realm) => { if (error) { reject(error); return; } - + TestCase.assertTrue(progressCalled); resolve(); }, @@ -645,5 +645,5 @@ module.exports = { }); }); }); - }, + }, }