Merge pull request #1302 from realm/blagoev/promise3

Blagoev/promise3
This commit is contained in:
blagoev 2017-09-13 15:07:53 +03:00 committed by GitHub
commit 03bc224374
8 changed files with 97 additions and 30 deletions

View File

@ -9,9 +9,11 @@ X.Y.Z Release notes
* Added additional parameter for `Realm.open` and `Realm.openAsync` for download progress notifications * Added additional parameter for `Realm.open` and `Realm.openAsync` for download progress notifications
* Added `Realm.deleteFile` for deleting a Realm (#363). * Added `Realm.deleteFile` for deleting a Realm (#363).
* Added `Realm.deleteModel` for deleting a Realm model in a migration (#573). * Added `Realm.deleteModel` for deleting a Realm model in a migration (#573).
* `Realm.Sync.User.login`, `Realm.Sync.User.register`, and `Realm.Sync.User.registerWithProvider` return Promises and deprecate the callback style for them. Callbacks will continue to work for backward compatibility.
### Bug fixes ### Bug fixes
* Adding missing TypeScript definitions; Permissions (#1283), `setFeatureToken()`, and instructions (#1298). * Adding missing TypeScript definitions; Permissions (#1283), `setFeatureToken()`, and instructions (#1298).
* Removed `loginWithProvider` from TypeScript definition files. This API never existed and was incorrectly added.
1.11.1 Release notes (2017-9-1) 1.11.1 Release notes (2017-9-1)
============================================================= =============================================================

View File

@ -135,9 +135,10 @@ class User {
* @param {string} server - authentication server * @param {string} server - authentication server
* @param {string} username * @param {string} username
* @param {string} password * @param {string} password
* @param {function(error, user)} callback - called with the following arguments: * @param {function(error, user)} [callback] - called with the following arguments:
* - `error` - an Error object is provided on failure * - `error` - an Error object is provided on failure
* - `user` - a valid User object on success * - `user` - a valid User object on success
* @returns {void|Promise<User>} Returns a promise with a user if the callback was not specified
*/ */
static login(server, username, password, callback) {} static login(server, username, password, callback) {}
@ -148,9 +149,10 @@ class User {
* @param {string} options.provider - The provider type * @param {string} options.provider - The provider type
* @param {string} options.providerToken - The access token for the given provider * @param {string} options.providerToken - The access token for the given provider
* @param {object} [options.userInfo] - A map containing additional data required by the provider * @param {object} [options.userInfo] - A map containing additional data required by the provider
* @param {function(error, User)} callback - called with the following arguments: * @param {function(error, User)} [callback] - an optional callback called with the following arguments:
* - `error` - an Error object is provided on failure * - `error` - an Error object is provided on failure
* - `user` - a valid User object on success * - `user` - a valid User object on success
* @return {void|Promise<User>} Returns a promise with a user if the callback was not specified
*/ */
static registerWithProvider(server, options, callback) {} static registerWithProvider(server, options, callback) {}
@ -159,9 +161,10 @@ class User {
* @param {string} server - authentication server * @param {string} server - authentication server
* @param {string} username * @param {string} username
* @param {string} password * @param {string} password
* @param {function(error, user)} callback - called with the following arguments: * @param {function(error, user)} [callback] - called with the following arguments:
* - `error` - an Error object is provided on failure * - `error` - an Error object is provided on failure
* - `user` - a valid User object on success * - `user` - a valid User object on success
* @return {void|Promise<User>} Returns a promise with a user if the callback was not specified
*/ */
static register(server, username, password, callback) {} static register(server, username, password, callback) {}

View File

@ -19,7 +19,12 @@
'use strict'; 'use strict';
function AuthError(problem) { function AuthError(problem) {
Error.call(this, problem.title); const error = Error.call(this, problem.title);
this.name = 'AuthError';
this.message = error.message;
this.stack = error.stack;
Object.assign(this, problem); Object.assign(this, problem);
} }

View File

@ -77,6 +77,9 @@ module.exports = function(realmConstructor) {
}, },
openAsync(config, callback, progressCallback) { openAsync(config, callback, progressCallback) {
const message = "Realm.openAsync is now deprecated in favor of Realm.open. This function will be removed in future versions.";
(console.warn || console.log).call(console, message);
realmConstructor._waitForDownload(config, realmConstructor._waitForDownload(config,
(syncSession) => { (syncSession) => {
if (progressCallback) { if (progressCallback) {
@ -93,7 +96,7 @@ module.exports = function(realmConstructor) {
//FIXME: RN hangs here. Remove when node's makeCallback alternative is implemented //FIXME: RN hangs here. Remove when node's makeCallback alternative is implemented
setTimeout(() => { callback(null, syncedRealm); }, 1); setTimeout(() => { callback(null, syncedRealm); }, 1);
} catch (e) { } catch (e) {
callback(e); setTimeout(() => { callback(e); }, 1);
} }
} }
}); });

19
lib/index.d.ts vendored
View File

@ -264,10 +264,25 @@ declare namespace Realm.Sync {
readonly server: string; readonly server: string;
readonly token: string; readonly token: string;
static adminUser(adminToken: string, server?: string): User; static adminUser(adminToken: string, server?: string): User;
/**
* @deprecated, to be removed in future versions
*/
static login(server: string, username: string, password: string, callback: (error: any, user: User) => void): void; static login(server: string, username: string, password: string, callback: (error: any, user: User) => void): void;
static loginWithProvider(server: string, provider: string, providerToken: string, callback: (error: any, user: User) => void): void; static login(server: string, username: string, password: string): Promise<Realm.Sync.User>;
/**
* @deprecated, to be removed in future versions
*/
static register(server: string, username: string, password: string, callback: (error: any, user: User) => void): void; static register(server: string, username: string, password: string, callback: (error: any, user: User) => void): void;
static register(server: string, username: string, password: string): Promise<Realm.Sync.User>;
/**
* @deprecated, to be removed in versions
*/
static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }, callback: (error: Error | null, user: User | null) => void): void; static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }, callback: (error: Error | null, user: User | null) => void): void;
static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }): Promise<Realm.Sync.User>;
logout(): void; logout(): void;
openManagementRealm(): Realm; openManagementRealm(): Realm;
retrieveAccount(provider: string, username: string): Promise<Account>; retrieveAccount(provider: string, username: string): Promise<Account>;
@ -375,6 +390,7 @@ declare namespace Realm.Sync {
function removeListener(regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void; function removeListener(regex: string, name: string, changeCallback: (changeEvent: ChangeEvent) => void): void;
function setLogLevel(logLevel: 'all' | 'trace' | 'debug' | 'detail' | 'info' | 'warn' | 'error' | 'fatal' | 'off'): void; function setLogLevel(logLevel: 'all' | 'trace' | 'debug' | 'detail' | 'info' | 'warn' | 'error' | 'fatal' | 'off'): void;
function setFeatureToken(token: string): void; function setFeatureToken(token: string): void;
/** /**
* @deprecated, to be removed in 2.0 * @deprecated, to be removed in 2.0
*/ */
@ -446,6 +462,7 @@ declare class Realm {
*/ */
static open(config: Realm.Configuration): ProgressPromise; static open(config: Realm.Configuration): ProgressPromise;
/** /**
* @deprecated in favor of `Realm.open`
* Open a realm asynchronously with a callback. If the realm is synced, it will be fully synchronized before it is available. * Open a realm asynchronously with a callback. If the realm is synced, it will be fully synchronized before it is available.
* @param {Configuration} config * @param {Configuration} config
* @param {Function} callback will be called when the realm is ready. * @param {Function} callback will be called when the realm is ready.

View File

@ -114,6 +114,15 @@ function refreshAccessToken(user, localRealmPath, realmUrl) {
}); });
} }
/**
* The base authentication method. It fires a JSON POST to the server parameter plus the auth url
* For example, if the server parameter is `http://myapp.com`, this url will post to `http://myapp.com/auth`
* @param {object} userConstructor
* @param {string} server the http or https server url
* @param {object} json the json to post to the auth endpoint
* @param {Function} callback an optional callback with an error and user parameter
* @returns {Promise} only returns a promise if the callback parameter was omitted
*/
function _authenticate(userConstructor, server, json, callback) { function _authenticate(userConstructor, server, json, callback) {
json.app_id = ''; json.app_id = '';
const url = auth_url(server); const url = auth_url(server);
@ -123,21 +132,32 @@ function _authenticate(userConstructor, server, json, callback) {
headers: postHeaders, headers: postHeaders,
open_timeout: 5000 open_timeout: 5000
}; };
performFetch(url, options)
const promise = performFetch(url, options)
.then((response) => { .then((response) => {
if (response.status !== 200) { if (response.status !== 200) {
return response.json().then((body) => callback(new AuthError(body))); return response.json().then((body) => Promise.reject(new AuthError(body)));
} else { } else {
return response.json().then(function (body) { return response.json().then(function (body) {
// TODO: validate JSON // TODO: validate JSON
const token = body.refresh_token.token; const token = body.refresh_token.token;
const identity = body.refresh_token.token_data.identity; const identity = body.refresh_token.token_data.identity;
const isAdmin = body.refresh_token.token_data.is_admin; const isAdmin = body.refresh_token.token_data.is_admin;
callback(undefined, userConstructor.createUser(server, identity, token, false, isAdmin)); return userConstructor.createUser(server, identity, token, false, isAdmin);
}) });
} }
});
if (callback) {
promise.then(user => {
callback(null, user);
}) })
.catch(callback); .catch(err => {
callback(err);
});
} else {
return promise;
}
} }
const staticMethods = { const staticMethods = {
@ -164,20 +184,34 @@ const staticMethods = {
register(server, username, password, callback) { register(server, username, password, callback) {
checkTypes(arguments, ['string', 'string', 'string', 'function']); checkTypes(arguments, ['string', 'string', 'string', 'function']);
_authenticate(this, server, { const json = {
provider: 'password', provider: 'password',
user_info: { password: password, register: true }, user_info: { password: password, register: true },
data: username data: username
}, callback); };
if (callback) {
const message = "register(..., callback) is now deprecated in favor of register(): Promise<User>. This function argument will be removed in future versions.";
(console.warn || console.log).call(console, message);
}
return _authenticate(this, server, json, callback);
}, },
login(server, username, password, callback) { login(server, username, password, callback) {
checkTypes(arguments, ['string', 'string', 'string', 'function']); checkTypes(arguments, ['string', 'string', 'string', 'function']);
_authenticate(this, server, { const json = {
provider: 'password', provider: 'password',
user_info: { password: password }, user_info: { password: password },
data: username data: username
}, callback); };
if (callback) {
const message = "login(..., callback) is now deprecated in favor of login(): Promise<User>. This function argument will be removed in future versions.";
(console.warn || console.log).call(console, message);
}
return _authenticate(this, server, json, callback);
}, },
registerWithProvider(server, options, callback) { registerWithProvider(server, options, callback) {
@ -195,16 +229,21 @@ const staticMethods = {
checkTypes(arguments, ['string', 'object', 'function']); checkTypes(arguments, ['string', 'object', 'function']);
} }
let reqOptions = { let json = {
provider: options.provider, provider: options.provider,
data: options.providerToken, data: options.providerToken,
}; };
if (options.userInfo) { if (options.userInfo) {
reqOptions.user_info = options.userInfo; json.user_info = options.userInfo;
} }
_authenticate(this, server, reqOptions, callback); if (callback) {
const message = "registerWithProvider(..., callback) is now deprecated in favor of registerWithProvider(): Promise<User>. This function argument will be removed in future versions.";
(console.warn || console.log).call(console, message);
}
return _authenticate(this, server, json, callback);
}, },
_refreshAccessToken: refreshAccessToken _refreshAccessToken: refreshAccessToken
@ -233,13 +272,11 @@ const instanceMethods = {
}, },
retrieveAccount(provider, provider_id) { retrieveAccount(provider, provider_id) {
checkTypes(arguments, ['string', 'string']); checkTypes(arguments, ['string', 'string']);
const url = url_parse(this.server); const url = url_parse(this.server);
url.set('pathname', `/api/providers/${provider}/accounts/${provider_id}`); url.set('pathname', `/api/providers/${provider}/accounts/${provider_id}`);
const headers = { const headers = {
Authorization: this.token Authorization: this.token
}; };
const options = { const options = {
method: 'GET', method: 'GET',
headers, headers,

View File

@ -36,7 +36,7 @@ Realm.Sync.User.register('http://localhost:9080', username, 'password', (error,
Realm.Sync.User.login('http://localhost:9080', username, 'password', (err, loggedUser) => { Realm.Sync.User.login('http://localhost:9080', username, 'password', (err, loggedUser) => {
if (err) { if (err) {
const loginError = JSON.stringify(err); const loginError = JSON.stringify(err);
console.error("download-api-helper failed:\n User.register() error:\n" + registrationError + "\n User.login() error:\n" + loginError); console.error("download-api-helper failed:\n User.register() error:\n" + err + "\n" + registrationError + "\n User.login() error:\n" + loginError);
process.exit(-2); process.exit(-2);
} }
else { else {

View File

@ -198,7 +198,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const accessTokenRefreshed = this; const accessTokenRefreshed = this;
let successCounter = 0; let successCounter = 0;
@ -251,7 +251,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
const accessTokenRefreshed = this; const accessTokenRefreshed = this;
let successCounter = 0; let successCounter = 0;
let progressNotificationCalled = false; let progressNotificationCalled = false;
@ -287,7 +287,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let progressNotificationCalled = false; let progressNotificationCalled = false;
let config = { let config = {
@ -334,7 +334,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const accessTokenRefreshed = this; const accessTokenRefreshed = this;
let successCounter = 0; let successCounter = 0;
@ -439,7 +439,7 @@ module.exports = {
}, },
testErrorHandling() { testErrorHandling() {
return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => { return Realm.Sync.User.register('http://localhost:9080', uuid(), 'password').then(user => {
return new Promise((resolve, _reject) => { return new Promise((resolve, _reject) => {
const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm' } }; const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm' } };
config.sync.error = (sender, error) => { config.sync.error = (sender, error) => {
@ -472,7 +472,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let config = { let config = {
sync: { sync: {
@ -507,7 +507,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let config = { let config = {
sync: { sync: {
@ -574,7 +574,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let config = { let config = {
sync: { sync: {
@ -613,7 +613,7 @@ module.exports = {
return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH)
.then(() => { .then(() => {
return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let config = { let config = {
sync: { sync: {