Merge branch 'internals-refactor'

This commit is contained in:
Chris Bianca 2018-01-03 20:01:16 +00:00
commit 40125d8eb6
51 changed files with 1043 additions and 1036 deletions

View File

@ -1,4 +1,5 @@
#import "RNFirebase.h" #import "RNFirebase.h"
#import "RNFirebaseUtil.h"
#import <FirebaseCore/FirebaseCore.h> #import <FirebaseCore/FirebaseCore.h>
@implementation RNFirebase @implementation RNFirebase
@ -21,14 +22,14 @@ RCT_EXPORT_MODULE(RNFirebase);
* @return * @return
*/ */
RCT_EXPORT_METHOD(initializeApp: RCT_EXPORT_METHOD(initializeApp:
(NSString *) appName (NSString *) appDisplayName
options: options:
(NSDictionary *) options (NSDictionary *) options
callback: callback:
(RCTResponseSenderBlock) callback) { (RCTResponseSenderBlock) callback) {
dispatch_sync(dispatch_get_main_queue(), ^{ dispatch_sync(dispatch_get_main_queue(), ^{
FIRApp *existingApp = [FIRApp appNamed:appName]; FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName];
if (!existingApp) { if (!existingApp) {
FIROptions *firOptions = [[FIROptions alloc] initWithGoogleAppID:[options valueForKey:@"appId"] GCMSenderID:[options valueForKey:@"messagingSenderId"]]; FIROptions *firOptions = [[FIROptions alloc] initWithGoogleAppID:[options valueForKey:@"appId"] GCMSenderID:[options valueForKey:@"messagingSenderId"]];
@ -43,6 +44,7 @@ RCT_EXPORT_METHOD(initializeApp:
firOptions.deepLinkURLScheme = [options valueForKey:@"deepLinkURLScheme"]; firOptions.deepLinkURLScheme = [options valueForKey:@"deepLinkURLScheme"];
firOptions.bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]; firOptions.bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
NSString *appName = [RNFirebaseUtil getAppName:appDisplayName];
[FIRApp configureWithName:appName options:firOptions]; [FIRApp configureWithName:appName options:firOptions];
} }
@ -55,13 +57,13 @@ RCT_EXPORT_METHOD(initializeApp:
* @return * @return
*/ */
RCT_EXPORT_METHOD(deleteApp: RCT_EXPORT_METHOD(deleteApp:
(NSString *) appName (NSString *) appDisplayName
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *existingApp = [FIRApp appNamed:appName]; FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName];
if (!existingApp) { if (!existingApp) {
return resolve([NSNull null]); return resolve([NSNull null]);
@ -90,7 +92,7 @@ RCT_EXPORT_METHOD(deleteApp:
NSMutableDictionary *appOptions = [NSMutableDictionary new]; NSMutableDictionary *appOptions = [NSMutableDictionary new];
FIRApp *firApp = firApps[key]; FIRApp *firApp = firApps[key];
FIROptions *firOptions = [firApp options]; FIROptions *firOptions = [firApp options];
appOptions[@"name"] = firApp.name; appOptions[@"name"] = [RNFirebaseUtil getAppDisplayName:firApp.name];
appOptions[@"apiKey"] = firOptions.APIKey; appOptions[@"apiKey"] = firOptions.APIKey;
appOptions[@"appId"] = firOptions.googleAppID; appOptions[@"appId"] = firOptions.googleAppID;
appOptions[@"databaseURL"] = firOptions.databaseURL; appOptions[@"databaseURL"] = firOptions.databaseURL;

View File

@ -3,11 +3,15 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <React/RCTEventEmitter.h> #import <React/RCTEventEmitter.h>
#import <Firebase.h>
@interface RNFirebaseUtil : NSObject @interface RNFirebaseUtil : NSObject
+ (FIRApp *)getApp:(NSString *)appDisplayName;
+ (NSString *)getAppName:(NSString *)appDisplayName;
+ (NSString *)getAppDisplayName:(NSString *)appName;
+ (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body; + (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body;
+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter appName:(NSString *)appName name:(NSString *)name body:(NSDictionary *)body; + (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body;
@end @end

View File

@ -2,6 +2,28 @@
@implementation RNFirebaseUtil @implementation RNFirebaseUtil
static NSString *const DEFAULT_APP_DISPLAY_NAME = @"[DEFAULT]";
static NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT";
+ (FIRApp *)getApp:(NSString *)appDisplayName {
NSString *appName = [RNFirebaseUtil getAppName:appDisplayName];
return [FIRApp appNamed:appName];
}
+ (NSString *)getAppName:(NSString *)appDisplayName {
if ([appDisplayName isEqualToString:DEFAULT_APP_DISPLAY_NAME]) {
return DEFAULT_APP_NAME;
}
return appDisplayName;
}
+ (NSString *)getAppDisplayName:(NSString *)appName {
if ([appName isEqualToString:DEFAULT_APP_NAME]) {
return DEFAULT_APP_DISPLAY_NAME;
}
return appName;
}
+ (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body { + (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body {
@try { @try {
// TODO: Temporary fix for https://github.com/invertase/react-native-firebase/issues/233 // TODO: Temporary fix for https://github.com/invertase/react-native-firebase/issues/233
@ -14,10 +36,10 @@
} }
} }
+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter appName:(NSString *)appName name:(NSString *)name body:(NSDictionary *)body { + (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body {
// Add the appName to the body // Add the appName to the body
NSMutableDictionary *newBody = [body mutableCopy]; NSMutableDictionary *newBody = [body mutableCopy];
newBody[@"appName"] = appName; newBody[@"appName"] = [RNFirebaseUtil getAppDisplayName:app.name];
[RNFirebaseUtil sendJSEvent:emitter name:name body:newBody]; [RNFirebaseUtil sendJSEvent:emitter name:name body:newBody];
} }

View File

@ -23,19 +23,19 @@ RCT_EXPORT_MODULE();
*/ */
RCT_EXPORT_METHOD(addAuthStateListener: RCT_EXPORT_METHOD(addAuthStateListener:
(NSString *) appName) { (NSString *) appDisplayName) {
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
if (![_authStateHandlers valueForKey:appName]) { if (![_authStateHandlers valueForKey:firApp.name]) {
FIRApp *firApp = [FIRApp appNamed:appName];
FIRAuthStateDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) { FIRAuthStateDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) {
if (user != nil) { if (user != nil) {
[RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}];
} else { } else {
[RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(false)}]; [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(false)}];
} }
}]; }];
_authStateHandlers[appName] = [NSValue valueWithNonretainedObject:newListenerHandle]; _authStateHandlers[firApp.name] = [NSValue valueWithNonretainedObject:newListenerHandle];
} }
} }
@ -44,12 +44,12 @@ RCT_EXPORT_METHOD(addAuthStateListener:
*/ */
RCT_EXPORT_METHOD(removeAuthStateListener: RCT_EXPORT_METHOD(removeAuthStateListener:
(NSString *) appName) { (NSString *) appDisplayName) {
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
if ([_authStateHandlers valueForKey:appName]) { if ([_authStateHandlers valueForKey:firApp.name]) {
FIRApp *firApp = [FIRApp appNamed:appName]; [[FIRAuth authWithApp:firApp] removeAuthStateDidChangeListener:[_authStateHandlers valueForKey:firApp.name]];
[[FIRAuth authWithApp:firApp] removeAuthStateDidChangeListener:[_authStateHandlers valueForKey:appName]]; [_authStateHandlers removeObjectForKey:firApp.name];
[_authStateHandlers removeObjectForKey:appName];
} }
} }
@ -58,19 +58,19 @@ RCT_EXPORT_METHOD(removeAuthStateListener:
*/ */
RCT_EXPORT_METHOD(addIdTokenListener: RCT_EXPORT_METHOD(addIdTokenListener:
(NSString *) appName) { (NSString *) appDisplayName) {
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
if (![_idTokenHandlers valueForKey:appName]) { if (![_idTokenHandlers valueForKey:firApp.name]) {
FIRApp *firApp = [FIRApp appNamed:appName];
FIRIDTokenDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addIDTokenDidChangeListener:^(FIRAuth * _Nonnull auth, FIRUser * _Nullable user) { FIRIDTokenDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addIDTokenDidChangeListener:^(FIRAuth * _Nonnull auth, FIRUser * _Nullable user) {
if (user != nil) { if (user != nil) {
[RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}];
} else { } else {
[RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(false)}]; [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(false)}];
} }
}]; }];
_idTokenHandlers[appName] = [NSValue valueWithNonretainedObject:newListenerHandle]; _idTokenHandlers[firApp.name] = [NSValue valueWithNonretainedObject:newListenerHandle];
} }
} }
@ -79,11 +79,12 @@ RCT_EXPORT_METHOD(addIdTokenListener:
*/ */
RCT_EXPORT_METHOD(removeIdTokenListener: RCT_EXPORT_METHOD(removeIdTokenListener:
(NSString *) appName) { (NSString *) appDisplayName) {
if ([_idTokenHandlers valueForKey:appName]) { FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRApp *firApp = [FIRApp appNamed:appName];
[[FIRAuth authWithApp:firApp] removeIDTokenDidChangeListener:[_idTokenHandlers valueForKey:appName]]; if ([_idTokenHandlers valueForKey:firApp.name]) {
[_idTokenHandlers removeObjectForKey:appName]; [[FIRAuth authWithApp:firApp] removeIDTokenDidChangeListener:[_idTokenHandlers valueForKey:firApp.name]];
[_idTokenHandlers removeObjectForKey:firApp.name];
} }
} }
@ -97,12 +98,12 @@ RCT_EXPORT_METHOD(removeIdTokenListener:
@return @return
*/ */
RCT_EXPORT_METHOD(signOut: RCT_EXPORT_METHOD(signOut:
(NSString *) appName (NSString *) appDisplayName
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
@ -125,12 +126,12 @@ RCT_EXPORT_METHOD(signOut:
@return @return
*/ */
RCT_EXPORT_METHOD(signInAnonymously: RCT_EXPORT_METHOD(signInAnonymously:
(NSString *) appName (NSString *) appDisplayName
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] signInAnonymouslyWithCompletion:^(FIRUser *user, NSError *error) { [[FIRAuth authWithApp:firApp] signInAnonymouslyWithCompletion:^(FIRUser *user, NSError *error) {
if (error) { if (error) {
@ -152,7 +153,7 @@ RCT_EXPORT_METHOD(signInAnonymously:
@return return @return return
*/ */
RCT_EXPORT_METHOD(signInWithEmailAndPassword: RCT_EXPORT_METHOD(signInWithEmailAndPassword:
(NSString *) appName (NSString *) appDisplayName
email: email:
(NSString *) email (NSString *) email
pass: pass:
@ -161,7 +162,7 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] signInWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { [[FIRAuth authWithApp:firApp] signInWithEmail:email password:password completion:^(FIRUser *user, NSError *error) {
if (error) { if (error) {
@ -182,7 +183,7 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword:
@return return @return return
*/ */
RCT_EXPORT_METHOD(createUserWithEmailAndPassword: RCT_EXPORT_METHOD(createUserWithEmailAndPassword:
(NSString *) appName (NSString *) appDisplayName
email: email:
(NSString *) email (NSString *) email
pass: pass:
@ -191,7 +192,7 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] createUserWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { [[FIRAuth authWithApp:firApp] createUserWithEmail:email password:password completion:^(FIRUser *user, NSError *error) {
if (error) { if (error) {
@ -210,12 +211,12 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword:
@return return @return return
*/ */
RCT_EXPORT_METHOD(delete: RCT_EXPORT_METHOD(delete:
(NSString *) appName (NSString *) appDisplayName
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
if (user) { if (user) {
@ -239,12 +240,12 @@ RCT_EXPORT_METHOD(delete:
@return return @return return
*/ */
RCT_EXPORT_METHOD(reload: RCT_EXPORT_METHOD(reload:
(NSString *) appName (NSString *) appDisplayName
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
@ -262,11 +263,11 @@ RCT_EXPORT_METHOD(reload:
@param RCTPromiseRejectBlock reject @param RCTPromiseRejectBlock reject
@return return @return return
*/ */
RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appName RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appDisplayName
actionCodeSettings:(NSDictionary *) actionCodeSettings actionCodeSettings:(NSDictionary *) actionCodeSettings
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
if (user) { if (user) {
@ -298,14 +299,14 @@ RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appName
@return return @return return
*/ */
RCT_EXPORT_METHOD(updateEmail: RCT_EXPORT_METHOD(updateEmail:
(NSString *) appName (NSString *) appDisplayName
email: email:
(NSString *) email (NSString *) email
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
if (user) { if (user) {
@ -330,14 +331,14 @@ RCT_EXPORT_METHOD(updateEmail:
@return return @return return
*/ */
RCT_EXPORT_METHOD(updatePassword: RCT_EXPORT_METHOD(updatePassword:
(NSString *) appName (NSString *) appDisplayName
password: password:
(NSString *) password (NSString *) password
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
@ -364,14 +365,14 @@ RCT_EXPORT_METHOD(updatePassword:
@return return @return return
*/ */
RCT_EXPORT_METHOD(updateProfile: RCT_EXPORT_METHOD(updateProfile:
(NSString *) appName (NSString *) appDisplayName
props: props:
(NSDictionary *) props (NSDictionary *) props
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
@ -412,14 +413,14 @@ RCT_EXPORT_METHOD(updateProfile:
@return @return
*/ */
RCT_EXPORT_METHOD(getToken: RCT_EXPORT_METHOD(getToken:
(NSString *) appName (NSString *) appDisplayName
forceRefresh: forceRefresh:
(BOOL) forceRefresh (BOOL) forceRefresh
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
@ -447,7 +448,7 @@ RCT_EXPORT_METHOD(getToken:
@return @return
*/ */
RCT_EXPORT_METHOD(signInWithCredential: RCT_EXPORT_METHOD(signInWithCredential:
(NSString *) appName (NSString *) appDisplayName
provider: provider:
(NSString *) provider (NSString *) provider
token: token:
@ -458,7 +459,7 @@ RCT_EXPORT_METHOD(signInWithCredential:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
@ -485,7 +486,7 @@ RCT_EXPORT_METHOD(signInWithCredential:
@return @return
*/ */
RCT_EXPORT_METHOD(confirmPasswordReset: RCT_EXPORT_METHOD(confirmPasswordReset:
(NSString *) appName (NSString *) appDisplayName
code: code:
(NSString *) code (NSString *) code
newPassword: newPassword:
@ -494,8 +495,8 @@ RCT_EXPORT_METHOD(confirmPasswordReset:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] confirmPasswordResetWithCode:code newPassword:newPassword completion:^(NSError *_Nullable error) { [[FIRAuth authWithApp:firApp] confirmPasswordResetWithCode:code newPassword:newPassword completion:^(NSError *_Nullable error) {
if (error) { if (error) {
[self promiseRejectAuthException:reject error:error]; [self promiseRejectAuthException:reject error:error];
@ -515,15 +516,15 @@ RCT_EXPORT_METHOD(confirmPasswordReset:
* @return * @return
*/ */
RCT_EXPORT_METHOD(applyActionCode: RCT_EXPORT_METHOD(applyActionCode:
(NSString *) appName (NSString *) appDisplayName
code: code:
(NSString *) code (NSString *) code
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] applyActionCode:code completion:^(NSError *_Nullable error) { [[FIRAuth authWithApp:firApp] applyActionCode:code completion:^(NSError *_Nullable error) {
if (error) { if (error) {
[self promiseRejectAuthException:reject error:error]; [self promiseRejectAuthException:reject error:error];
@ -542,15 +543,15 @@ RCT_EXPORT_METHOD(applyActionCode:
* @return * @return
*/ */
RCT_EXPORT_METHOD(checkActionCode: RCT_EXPORT_METHOD(checkActionCode:
(NSString *) appName (NSString *) appDisplayName
code: code:
(NSString *) code (NSString *) code
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] checkActionCode:code completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) { [[FIRAuth authWithApp:firApp] checkActionCode:code completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) {
if (error) { if (error) {
[self promiseRejectAuthException:reject error:error]; [self promiseRejectAuthException:reject error:error];
@ -586,12 +587,12 @@ RCT_EXPORT_METHOD(checkActionCode:
@param RCTPromiseRejectBlock reject @param RCTPromiseRejectBlock reject
@return @return
*/ */
RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appDisplayName
email:(NSString *) email email:(NSString *) email
actionCodeSettings:(NSDictionary *) actionCodeSettings actionCodeSettings:(NSDictionary *) actionCodeSettings
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
id handler = ^(NSError *_Nullable error) { id handler = ^(NSError *_Nullable error) {
if (error) { if (error) {
@ -600,7 +601,7 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName
[self promiseNoUser:resolve rejecter:reject isError:NO]; [self promiseNoUser:resolve rejecter:reject isError:NO];
} }
}; };
if (actionCodeSettings) { if (actionCodeSettings) {
FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings]; FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings];
[[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email actionCodeSettings:settings completion:handler]; [[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email actionCodeSettings:settings completion:handler];
@ -617,12 +618,12 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName
@return @return
*/ */
RCT_EXPORT_METHOD(getCurrentUser: RCT_EXPORT_METHOD(getCurrentUser:
(NSString *) appName (NSString *) appDisplayName
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
[self promiseWithUser:resolve rejecter:reject user:user]; [self promiseWithUser:resolve rejecter:reject user:user];
@ -637,14 +638,14 @@ RCT_EXPORT_METHOD(getCurrentUser:
@return @return
*/ */
RCT_EXPORT_METHOD(signInWithCustomToken: RCT_EXPORT_METHOD(signInWithCustomToken:
(NSString *) appName (NSString *) appDisplayName
customToken: customToken:
(NSString *) customToken (NSString *) customToken
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] signInWithCustomToken:customToken completion:^(FIRUser *user, NSError *error) { [[FIRAuth authWithApp:firApp] signInWithCustomToken:customToken completion:^(FIRUser *user, NSError *error) {
if (error) { if (error) {
@ -663,11 +664,11 @@ RCT_EXPORT_METHOD(signInWithCustomToken:
@param RCTPromiseRejectBlock reject @param RCTPromiseRejectBlock reject
@return @return
*/ */
RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appName RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appDisplayName
phoneNumber:(NSString *) phoneNumber phoneNumber:(NSString *) phoneNumber
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firApp]] verifyPhoneNumber:phoneNumber UIDelegate:nil completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firApp]] verifyPhoneNumber:phoneNumber UIDelegate:nil completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
if (error) { if (error) {
@ -684,17 +685,17 @@ RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appName
/** /**
verifyPhoneNumber verifyPhoneNumber
@param string phoneNumber @param string phoneNumber
@param RCTPromiseResolveBlock resolve @param RCTPromiseResolveBlock resolve
@param RCTPromiseRejectBlock reject @param RCTPromiseRejectBlock reject
@return @return
*/ */
RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appDisplayName
phoneNumber:(NSString *) phoneNumber phoneNumber:(NSString *) phoneNumber
requestKey:(NSString *) requestKey) { requestKey:(NSString *) requestKey) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firApp]] verifyPhoneNumber:phoneNumber UIDelegate:nil completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firApp]] verifyPhoneNumber:phoneNumber UIDelegate:nil completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
if (error) { if (error) {
NSDictionary * jsError = [self getJSError:(error)]; NSDictionary * jsError = [self getJSError:(error)];
@ -703,7 +704,7 @@ RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName
@"requestKey":requestKey, @"requestKey":requestKey,
@"state": @{@"error": jsError}, @"state": @{@"error": jsError},
}; };
[RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:PHONE_AUTH_STATE_CHANGED_EVENT body:body]; [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:PHONE_AUTH_STATE_CHANGED_EVENT body:body];
} else { } else {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:verificationID forKey:@"authVerificationID"]; [defaults setObject:verificationID forKey:@"authVerificationID"];
@ -712,16 +713,16 @@ RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName
@"requestKey":requestKey, @"requestKey":requestKey,
@"state": @{@"verificationId": verificationID}, @"state": @{@"verificationId": verificationID},
}; };
[RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:PHONE_AUTH_STATE_CHANGED_EVENT body:body]; [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:PHONE_AUTH_STATE_CHANGED_EVENT body:body];
} }
}]; }];
} }
RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appName RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appDisplayName
verificationCode:(NSString *) verificationCode verificationCode:(NSString *) verificationCode
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *verificationId = [defaults stringForKey:@"authVerificationID"]; NSString *verificationId = [defaults stringForKey:@"authVerificationID"];
FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationId verificationCode:verificationCode]; FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationId verificationCode:verificationCode];
@ -746,7 +747,7 @@ RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appName
@return @return
*/ */
RCT_EXPORT_METHOD(link: RCT_EXPORT_METHOD(link:
(NSString *) appName (NSString *) appDisplayName
provider: provider:
(NSString *) provider (NSString *) provider
authToken: authToken:
@ -757,7 +758,7 @@ RCT_EXPORT_METHOD(link:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
@ -791,14 +792,14 @@ RCT_EXPORT_METHOD(link:
@return @return
*/ */
RCT_EXPORT_METHOD(unlink: RCT_EXPORT_METHOD(unlink:
(NSString *) appName (NSString *) appDisplayName
providerId: providerId:
(NSString *) providerId (NSString *) providerId
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
if (user) { if (user) {
@ -825,7 +826,7 @@ RCT_EXPORT_METHOD(unlink:
@return @return
*/ */
RCT_EXPORT_METHOD(reauthenticate: RCT_EXPORT_METHOD(reauthenticate:
(NSString *) appName (NSString *) appDisplayName
provider: provider:
(NSString *) provider (NSString *) provider
authToken: authToken:
@ -836,7 +837,7 @@ RCT_EXPORT_METHOD(reauthenticate:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
@ -869,14 +870,14 @@ RCT_EXPORT_METHOD(reauthenticate:
@return @return
*/ */
RCT_EXPORT_METHOD(fetchProvidersForEmail: RCT_EXPORT_METHOD(fetchProvidersForEmail:
(NSString *) appName (NSString *) appDisplayName
email: email:
(NSString *) email (NSString *) email
resolver: resolver:
(RCTPromiseResolveBlock) resolve (RCTPromiseResolveBlock) resolve
rejecter: rejecter:
(RCTPromiseRejectBlock) reject) { (RCTPromiseRejectBlock) reject) {
FIRApp *firApp = [FIRApp appNamed:appName]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRAuth authWithApp:firApp] fetchProvidersForEmail:email completion:^(NSArray<NSString *> *_Nullable providers, NSError *_Nullable error) { [[FIRAuth authWithApp:firApp] fetchProvidersForEmail:email completion:^(NSArray<NSString *> *_Nullable providers, NSError *_Nullable error) {
if (error) { if (error) {
@ -962,14 +963,14 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
/** /**
Reject a promise with an auth exception Reject a promise with an auth exception
@param error NSError @param error NSError
*/ */
- (NSDictionary *)getJSError:(NSError *)error { - (NSDictionary *)getJSError:(NSError *)error {
NSString *code = @"auth/unknown"; NSString *code = @"auth/unknown";
NSString *message = [error localizedDescription]; NSString *message = [error localizedDescription];
NSString *nativeErrorMessage = [error localizedDescription]; NSString *nativeErrorMessage = [error localizedDescription];
switch (error.code) { switch (error.code) {
case FIRAuthErrorCodeInvalidCustomToken: case FIRAuthErrorCodeInvalidCustomToken:
code = @"auth/invalid-custom-token"; code = @"auth/invalid-custom-token";
@ -1043,7 +1044,7 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
code = @"auth/internal-error"; code = @"auth/internal-error";
message = @"An internal error has occurred, please try again."; message = @"An internal error has occurred, please try again.";
break; break;
// unsure of the below codes so leaving them as the default error message // unsure of the below codes so leaving them as the default error message
case FIRAuthErrorCodeTooManyRequests: case FIRAuthErrorCodeTooManyRequests:
code = @"auth/too-many-requests"; code = @"auth/too-many-requests";
@ -1078,7 +1079,7 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
default: default:
break; break;
} }
return @{ return @{
@"code": code, @"code": code,
@"message": message, @"message": message,

View File

@ -16,7 +16,7 @@
+ (void)handlePromise:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject databaseError:(NSError *)databaseError; + (void)handlePromise:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject databaseError:(NSError *)databaseError;
+ (FIRDatabase *)getDatabaseForApp:(NSString *)appName; + (FIRDatabase *)getDatabaseForApp:(NSString *)appDisplayName;
+ (NSDictionary *)getJSError:(NSError *)nativeError; + (NSDictionary *)getJSError:(NSError *)nativeError;

View File

@ -22,38 +22,38 @@ RCT_EXPORT_MODULE();
return self; return self;
} }
RCT_EXPORT_METHOD(goOnline:(NSString *) appName) { RCT_EXPORT_METHOD(goOnline:(NSString *) appDisplayName) {
[[RNFirebaseDatabase getDatabaseForApp:appName] goOnline]; [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOnline];
} }
RCT_EXPORT_METHOD(goOffline:(NSString *) appName) { RCT_EXPORT_METHOD(goOffline:(NSString *) appDisplayName) {
[[RNFirebaseDatabase getDatabaseForApp:appName] goOffline]; [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOffline];
} }
RCT_EXPORT_METHOD(setPersistence:(NSString *) appName RCT_EXPORT_METHOD(setPersistence:(NSString *) appDisplayName
state:(BOOL) state) { state:(BOOL) state) {
[RNFirebaseDatabase getDatabaseForApp:appName].persistenceEnabled = state; [RNFirebaseDatabase getDatabaseForApp:appDisplayName].persistenceEnabled = state;
} }
RCT_EXPORT_METHOD(setPersistenceCacheSizeBytes:(NSString *) appName RCT_EXPORT_METHOD(setPersistenceCacheSizeBytes:(NSString *) appDisplayName
size:(NSInteger *) size) { size:(NSInteger *) size) {
[RNFirebaseDatabase getDatabaseForApp:appName].persistenceCacheSizeBytes = (NSUInteger)size; [RNFirebaseDatabase getDatabaseForApp:appDisplayName].persistenceCacheSizeBytes = (NSUInteger)size;
} }
RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) { RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) {
[FIRDatabase setLoggingEnabled:enabled]; [FIRDatabase setLoggingEnabled:enabled];
} }
RCT_EXPORT_METHOD(keepSynced:(NSString *) appName RCT_EXPORT_METHOD(keepSynced:(NSString *) appDisplayName
key:(NSString *) key key:(NSString *) key
path:(NSString *) path path:(NSString *) path
modifiers:(NSArray *) modifiers modifiers:(NSArray *) modifiers
state:(BOOL) state) { state:(BOOL) state) {
FIRDatabaseQuery *query = [self getInternalReferenceForApp:appName key:key path:path modifiers:modifiers].query; FIRDatabaseQuery *query = [self getInternalReferenceForApp:appDisplayName key:key path:path modifiers:modifiers].query;
[query keepSynced:state]; [query keepSynced:state];
} }
RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appName RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appDisplayName
transactionId:(nonnull NSNumber *) transactionId transactionId:(nonnull NSNumber *) transactionId
updates:(NSDictionary *) updates) { updates:(NSDictionary *) updates) {
__block NSMutableDictionary *transactionState; __block NSMutableDictionary *transactionState;
@ -82,7 +82,7 @@ RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appName
} }
RCT_EXPORT_METHOD(transactionStart:(NSString *) appName RCT_EXPORT_METHOD(transactionStart:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
transactionId:(nonnull NSNumber *) transactionId transactionId:(nonnull NSNumber *) transactionId
applyLocally:(BOOL) applyLocally) { applyLocally:(BOOL) applyLocally) {
@ -90,13 +90,13 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName
NSMutableDictionary *transactionState = [NSMutableDictionary new]; NSMutableDictionary *transactionState = [NSMutableDictionary new];
dispatch_semaphore_t sema = dispatch_semaphore_create(0); dispatch_semaphore_t sema = dispatch_semaphore_create(0);
transactionState[@"semaphore"] = sema; transactionState[@"semaphore"] = sema;
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * [ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData *
_Nonnull currentData) { _Nonnull currentData) {
dispatch_barrier_async(_transactionQueue, ^{ dispatch_barrier_async(_transactionQueue, ^{
[_transactions setValue:transactionState forKey:transactionId]; [_transactions setValue:transactionState forKey:transactionId];
NSDictionary *updateMap = [self createTransactionUpdateMap:appName transactionId:transactionId updatesData:currentData]; NSDictionary *updateMap = [self createTransactionUpdateMap:appDisplayName transactionId:transactionId updatesData:currentData];
[RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:updateMap]; [RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:updateMap];
}); });
@ -123,7 +123,7 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName
} }
andCompletionBlock: andCompletionBlock:
^(NSError *_Nullable databaseError, BOOL committed, FIRDataSnapshot *_Nullable snapshot) { ^(NSError *_Nullable databaseError, BOOL committed, FIRDataSnapshot *_Nullable snapshot) {
NSDictionary *resultMap = [self createTransactionResultMap:appName transactionId:transactionId error:databaseError committed:committed snapshot:snapshot]; NSDictionary *resultMap = [self createTransactionResultMap:appDisplayName transactionId:transactionId error:databaseError committed:committed snapshot:snapshot];
[RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:resultMap]; [RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:resultMap];
} }
withLocalEvents: withLocalEvents:
@ -131,117 +131,117 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName
}); });
} }
RCT_EXPORT_METHOD(onDisconnectSet:(NSString *) appName RCT_EXPORT_METHOD(onDisconnectSet:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
props:(NSDictionary *) props props:(NSDictionary *) props
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref onDisconnectSetValue:props[@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [ref onDisconnectSetValue:props[@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *) appName RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
props:(NSDictionary *) props props:(NSDictionary *) props
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref onDisconnectUpdateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [ref onDisconnectUpdateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *) appName RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref onDisconnectRemoveValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [ref onDisconnectRemoveValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *) appName RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref cancelDisconnectOperationsWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [ref cancelDisconnectOperationsWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(set:(NSString *) appName RCT_EXPORT_METHOD(set:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
props:(NSDictionary *) props props:(NSDictionary *) props
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref setValue:[props valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [ref setValue:[props valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(setPriority:(NSString *) appName RCT_EXPORT_METHOD(setPriority:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
priority:(NSDictionary *) priority priority:(NSDictionary *) priority
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref setPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) { [ref setPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(setWithPriority:(NSString *) appName RCT_EXPORT_METHOD(setWithPriority:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
data:(NSDictionary *) data data:(NSDictionary *) data
priority:(NSDictionary *) priority priority:(NSDictionary *) priority
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref setValue:[data valueForKey:@"value"] andPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) { [ref setValue:[data valueForKey:@"value"] andPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(update:(NSString *) appName RCT_EXPORT_METHOD(update:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
props:(NSDictionary *) props props:(NSDictionary *) props
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref updateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [ref updateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(remove:(NSString *) appName RCT_EXPORT_METHOD(remove:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
[ref removeValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [ref removeValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) {
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}]; }];
} }
RCT_EXPORT_METHOD(once:(NSString *) appName RCT_EXPORT_METHOD(once:(NSString *) appDisplayName
key:(NSString *) key key:(NSString *) key
path:(NSString *) path path:(NSString *) path
modifiers:(NSArray *) modifiers modifiers:(NSArray *) modifiers
eventName:(NSString *) eventName eventName:(NSString *) eventName
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
RNFirebaseDatabaseReference *ref = [self getInternalReferenceForApp:appName key:key path:path modifiers:modifiers]; RNFirebaseDatabaseReference *ref = [self getInternalReferenceForApp:appDisplayName key:key path:path modifiers:modifiers];
[ref once:eventName resolver:resolve rejecter:reject]; [ref once:eventName resolver:resolve rejecter:reject];
} }
RCT_EXPORT_METHOD(on:(NSString *) appName RCT_EXPORT_METHOD(on:(NSString *) appDisplayName
props:(NSDictionary *) props) { props:(NSDictionary *) props) {
RNFirebaseDatabaseReference *ref = [self getCachedInternalReferenceForApp:appName props:props]; RNFirebaseDatabaseReference *ref = [self getCachedInternalReferenceForApp:appDisplayName props:props];
[ref on:props[@"eventType"] registration:props[@"registration"]]; [ref on:props[@"eventType"] registration:props[@"registration"]];
} }
@ -271,20 +271,20 @@ RCT_EXPORT_METHOD(off:(NSString *) key
} }
} }
+ (FIRDatabase *)getDatabaseForApp:(NSString *)appName { + (FIRDatabase *)getDatabaseForApp:(NSString *)appDisplayName {
FIRApp *app = [FIRApp appNamed:appName]; FIRApp *app = [RNFirebaseUtil getApp:appDisplayName];
return [FIRDatabase databaseForApp:app]; return [FIRDatabase databaseForApp:app];
} }
- (FIRDatabaseReference *)getReferenceForAppPath:(NSString *)appName path:(NSString *)path { - (FIRDatabaseReference *)getReferenceForAppPath:(NSString *)appDisplayName path:(NSString *)path {
return [[RNFirebaseDatabase getDatabaseForApp:appName] referenceWithPath:path]; return [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] referenceWithPath:path];
} }
- (RNFirebaseDatabaseReference *)getInternalReferenceForApp:(NSString *)appName key:(NSString *)key path:(NSString *)path modifiers:(NSArray *)modifiers { - (RNFirebaseDatabaseReference *)getInternalReferenceForApp:(NSString *)appDisplayName key:(NSString *)key path:(NSString *)path modifiers:(NSArray *)modifiers {
return [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self app:appName key:key refPath:path modifiers:modifiers]; return [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self appDisplayName:appDisplayName key:key refPath:path modifiers:modifiers];
} }
- (RNFirebaseDatabaseReference *)getCachedInternalReferenceForApp:(NSString *)appName props:(NSDictionary *)props { - (RNFirebaseDatabaseReference *)getCachedInternalReferenceForApp:(NSString *)appDisplayName props:(NSDictionary *)props {
NSString *key = props[@"key"]; NSString *key = props[@"key"];
NSString *path = props[@"path"]; NSString *path = props[@"path"];
NSDictionary *modifiers = props[@"modifiers"]; NSDictionary *modifiers = props[@"modifiers"];
@ -292,7 +292,7 @@ RCT_EXPORT_METHOD(off:(NSString *) key
RNFirebaseDatabaseReference *ref = _dbReferences[key]; RNFirebaseDatabaseReference *ref = _dbReferences[key];
if (ref == nil) { if (ref == nil) {
ref = [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self app:appName key:key refPath:path modifiers:modifiers]; ref = [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self appDisplayName:appDisplayName key:key refPath:path modifiers:modifiers];
_dbReferences[key] = ref; _dbReferences[key] = ref;
} }
return ref; return ref;
@ -380,20 +380,20 @@ RCT_EXPORT_METHOD(off:(NSString *) key
return errorMap; return errorMap;
} }
- (NSDictionary *)createTransactionUpdateMap:(NSString *)appName transactionId:(NSNumber *)transactionId updatesData:(FIRMutableData *)updatesData { - (NSDictionary *)createTransactionUpdateMap:(NSString *)appDisplayName transactionId:(NSNumber *)transactionId updatesData:(FIRMutableData *)updatesData {
NSMutableDictionary *updatesMap = [[NSMutableDictionary alloc] init]; NSMutableDictionary *updatesMap = [[NSMutableDictionary alloc] init];
[updatesMap setValue:transactionId forKey:@"id"]; [updatesMap setValue:transactionId forKey:@"id"];
[updatesMap setValue:@"update" forKey:@"type"]; [updatesMap setValue:@"update" forKey:@"type"];
[updatesMap setValue:appName forKey:@"appName"]; [updatesMap setValue:appDisplayName forKey:@"appName"];
[updatesMap setValue:updatesData.value forKey:@"value"]; [updatesMap setValue:updatesData.value forKey:@"value"];
return updatesMap; return updatesMap;
} }
- (NSDictionary *)createTransactionResultMap:(NSString *)appName transactionId:(NSNumber *)transactionId error:(NSError *)error committed:(BOOL)committed snapshot:(FIRDataSnapshot *)snapshot { - (NSDictionary *)createTransactionResultMap:(NSString *)appDisplayName transactionId:(NSNumber *)transactionId error:(NSError *)error committed:(BOOL)committed snapshot:(FIRDataSnapshot *)snapshot {
NSMutableDictionary *resultMap = [[NSMutableDictionary alloc] init]; NSMutableDictionary *resultMap = [[NSMutableDictionary alloc] init];
[resultMap setValue:transactionId forKey:@"id"]; [resultMap setValue:transactionId forKey:@"id"];
[resultMap setValue:appName forKey:@"appName"]; [resultMap setValue:appDisplayName forKey:@"appName"];
// TODO: no timeout on iOS // TODO: no timeout on iOS
[resultMap setValue:@(committed) forKey:@"committed"]; [resultMap setValue:@(committed) forKey:@"committed"];
// TODO: no interrupted on iOS // TODO: no interrupted on iOS

View File

@ -12,12 +12,12 @@
@interface RNFirebaseDatabaseReference : NSObject @interface RNFirebaseDatabaseReference : NSObject
@property RCTEventEmitter *emitter; @property RCTEventEmitter *emitter;
@property FIRDatabaseQuery *query; @property FIRDatabaseQuery *query;
@property NSString *app; @property NSString *appDisplayName;
@property NSString *key; @property NSString *key;
@property NSString *path; @property NSString *path;
@property NSMutableDictionary *listeners; @property NSMutableDictionary *listeners;
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter app:(NSString *)app key:(NSString *)key refPath:(NSString *)refPath modifiers:(NSArray *)modifiers; - (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName key:(NSString *)key refPath:(NSString *)refPath modifiers:(NSArray *)modifiers;
- (void)on:(NSString *) eventName registration:(NSDictionary *) registration; - (void)on:(NSString *) eventName registration:(NSDictionary *) registration;
- (void)once:(NSString *) eventType resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; - (void)once:(NSString *) eventType resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)removeEventListener:(NSString *)eventRegistrationKey; - (void)removeEventListener:(NSString *)eventRegistrationKey;

View File

@ -5,14 +5,14 @@
#if __has_include(<FirebaseDatabase/FIRDatabase.h>) #if __has_include(<FirebaseDatabase/FIRDatabase.h>)
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter - (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter
app:(NSString *) app appDisplayName:(NSString *) appDisplayName
key:(NSString *) key key:(NSString *) key
refPath:(NSString *) refPath refPath:(NSString *) refPath
modifiers:(NSArray *) modifiers { modifiers:(NSArray *) modifiers {
self = [super init]; self = [super init];
if (self) { if (self) {
_emitter = emitter; _emitter = emitter;
_app = app; _appDisplayName = appDisplayName;
_key = key; _key = key;
_path = refPath; _path = refPath;
_listeners = [[NSMutableDictionary alloc] init]; _listeners = [[NSMutableDictionary alloc] init];
@ -123,7 +123,7 @@
- (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(NSString *) path - (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(NSString *) path
modifiers:(NSArray *)modifiers { modifiers:(NSArray *)modifiers {
FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_app]; FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_appDisplayName];
FIRDatabaseQuery *query = [[firebaseDatabase reference] child:path]; FIRDatabaseQuery *query = [[firebaseDatabase reference] child:path];
for (NSDictionary *modifier in modifiers) { for (NSDictionary *modifier in modifiers) {

View File

@ -13,7 +13,7 @@
+ (void)promiseRejectException:(RCTPromiseRejectBlock)reject error:(NSError *)error; + (void)promiseRejectException:(RCTPromiseRejectBlock)reject error:(NSError *)error;
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appName; + (FIRFirestore *)getFirestoreForApp:(NSString *)appDisplayName;
+ (NSDictionary *)getJSError:(NSError *)nativeError; + (NSDictionary *)getJSError:(NSError *)nativeError;
@end @end

View File

@ -22,17 +22,17 @@ RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) {
[FIRFirestore enableLogging:enabled]; [FIRFirestore enableLogging:enabled];
} }
RCT_EXPORT_METHOD(collectionGet:(NSString *) appName RCT_EXPORT_METHOD(collectionGet:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
filters:(NSArray *) filters filters:(NSArray *) filters
orders:(NSArray *) orders orders:(NSArray *) orders
options:(NSDictionary *) options options:(NSDictionary *) options
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
[[self getCollectionForAppPath:appName path:path filters:filters orders:orders options:options] get:resolve rejecter:reject]; [[self getCollectionForAppPath:appDisplayName path:path filters:filters orders:orders options:options] get:resolve rejecter:reject];
} }
RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *) appName RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
filters:(NSArray *) filters filters:(NSArray *) filters
orders:(NSArray *) orders orders:(NSArray *) orders
@ -41,22 +41,22 @@ RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *) appName
[RNFirebaseFirestoreCollectionReference offSnapshot:listenerId]; [RNFirebaseFirestoreCollectionReference offSnapshot:listenerId];
} }
RCT_EXPORT_METHOD(collectionOnSnapshot:(NSString *) appName RCT_EXPORT_METHOD(collectionOnSnapshot:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
filters:(NSArray *) filters filters:(NSArray *) filters
orders:(NSArray *) orders orders:(NSArray *) orders
options:(NSDictionary *) options options:(NSDictionary *) options
listenerId:(nonnull NSString *) listenerId listenerId:(nonnull NSString *) listenerId
queryListenOptions:(NSDictionary *) queryListenOptions) { queryListenOptions:(NSDictionary *) queryListenOptions) {
RNFirebaseFirestoreCollectionReference *ref = [self getCollectionForAppPath:appName path:path filters:filters orders:orders options:options]; RNFirebaseFirestoreCollectionReference *ref = [self getCollectionForAppPath:appDisplayName path:path filters:filters orders:orders options:options];
[ref onSnapshot:listenerId queryListenOptions:queryListenOptions]; [ref onSnapshot:listenerId queryListenOptions:queryListenOptions];
} }
RCT_EXPORT_METHOD(documentBatch:(NSString *) appName RCT_EXPORT_METHOD(documentBatch:(NSString *) appDisplayName
writes:(NSArray *) writes writes:(NSArray *) writes
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appName]; FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appDisplayName];
FIRWriteBatch *batch = [firestore batch]; FIRWriteBatch *batch = [firestore batch];
for (NSDictionary *write in writes) { for (NSDictionary *write in writes) {
@ -89,56 +89,56 @@ RCT_EXPORT_METHOD(documentBatch:(NSString *) appName
}]; }];
} }
RCT_EXPORT_METHOD(documentDelete:(NSString *) appName RCT_EXPORT_METHOD(documentDelete:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
[[self getDocumentForAppPath:appName path:path] delete:resolve rejecter:reject]; [[self getDocumentForAppPath:appDisplayName path:path] delete:resolve rejecter:reject];
} }
RCT_EXPORT_METHOD(documentGet:(NSString *) appName RCT_EXPORT_METHOD(documentGet:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
[[self getDocumentForAppPath:appName path:path] get:resolve rejecter:reject]; [[self getDocumentForAppPath:appDisplayName path:path] get:resolve rejecter:reject];
} }
RCT_EXPORT_METHOD(documentGetAll:(NSString *) appName RCT_EXPORT_METHOD(documentGetAll:(NSString *) appDisplayName
documents:(NSString *) documents documents:(NSString *) documents
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
// Not supported on iOS out of the box // Not supported on iOS out of the box
} }
RCT_EXPORT_METHOD(documentOffSnapshot:(NSString *) appName RCT_EXPORT_METHOD(documentOffSnapshot:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
listenerId:(nonnull NSString *) listenerId) { listenerId:(nonnull NSString *) listenerId) {
[RNFirebaseFirestoreDocumentReference offSnapshot:listenerId]; [RNFirebaseFirestoreDocumentReference offSnapshot:listenerId];
} }
RCT_EXPORT_METHOD(documentOnSnapshot:(NSString *) appName RCT_EXPORT_METHOD(documentOnSnapshot:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
listenerId:(nonnull NSString *) listenerId listenerId:(nonnull NSString *) listenerId
docListenOptions:(NSDictionary *) docListenOptions) { docListenOptions:(NSDictionary *) docListenOptions) {
RNFirebaseFirestoreDocumentReference *ref = [self getDocumentForAppPath:appName path:path]; RNFirebaseFirestoreDocumentReference *ref = [self getDocumentForAppPath:appDisplayName path:path];
[ref onSnapshot:listenerId docListenOptions:docListenOptions]; [ref onSnapshot:listenerId docListenOptions:docListenOptions];
} }
RCT_EXPORT_METHOD(documentSet:(NSString *) appName RCT_EXPORT_METHOD(documentSet:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
data:(NSDictionary *) data data:(NSDictionary *) data
options:(NSDictionary *) options options:(NSDictionary *) options
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
[[self getDocumentForAppPath:appName path:path] set:data options:options resolver:resolve rejecter:reject]; [[self getDocumentForAppPath:appDisplayName path:path] set:data options:options resolver:resolve rejecter:reject];
} }
RCT_EXPORT_METHOD(documentUpdate:(NSString *) appName RCT_EXPORT_METHOD(documentUpdate:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
data:(NSDictionary *) data data:(NSDictionary *) data
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
[[self getDocumentForAppPath:appName path:path] update:data resolver:resolve rejecter:reject]; [[self getDocumentForAppPath:appDisplayName path:path] update:data resolver:resolve rejecter:reject];
} }
/* /*
@ -149,17 +149,17 @@ RCT_EXPORT_METHOD(documentUpdate:(NSString *) appName
reject([jsError valueForKey:@"code"], [jsError valueForKey:@"message"], error); reject([jsError valueForKey:@"code"], [jsError valueForKey:@"message"], error);
} }
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appName { + (FIRFirestore *)getFirestoreForApp:(NSString *)appDisplayName {
FIRApp *app = [FIRApp appNamed:appName]; FIRApp *app = [RNFirebaseUtil getApp:appDisplayName];
return [FIRFirestore firestoreForApp:app]; return [FIRFirestore firestoreForApp:app];
} }
- (RNFirebaseFirestoreCollectionReference *)getCollectionForAppPath:(NSString *)appName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options { - (RNFirebaseFirestoreCollectionReference *)getCollectionForAppPath:(NSString *)appDisplayName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options {
return [[RNFirebaseFirestoreCollectionReference alloc] initWithPathAndModifiers:self app:appName path:path filters:filters orders:orders options:options]; return [[RNFirebaseFirestoreCollectionReference alloc] initWithPathAndModifiers:self appDisplayName:appDisplayName path:path filters:filters orders:orders options:options];
} }
- (RNFirebaseFirestoreDocumentReference *)getDocumentForAppPath:(NSString *)appName path:(NSString *)path { - (RNFirebaseFirestoreDocumentReference *)getDocumentForAppPath:(NSString *)appDisplayName path:(NSString *)path {
return [[RNFirebaseFirestoreDocumentReference alloc] initWithPath:self app:appName path:path]; return [[RNFirebaseFirestoreDocumentReference alloc] initWithPath:self appDisplayName:appDisplayName path:path];
} }
// TODO: Move to error util for use in other modules // TODO: Move to error util for use in other modules

View File

@ -13,14 +13,14 @@
@interface RNFirebaseFirestoreCollectionReference : NSObject @interface RNFirebaseFirestoreCollectionReference : NSObject
@property RCTEventEmitter *emitter; @property RCTEventEmitter *emitter;
@property NSString *app; @property NSString *appDisplayName;
@property NSString *path; @property NSString *path;
@property NSArray *filters; @property NSArray *filters;
@property NSArray *orders; @property NSArray *orders;
@property NSDictionary *options; @property NSDictionary *options;
@property FIRQuery *query; @property FIRQuery *query;
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter app:(NSString *)app path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options; - (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options;
- (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; - (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
+ (void)offSnapshot:(NSString *)listenerId; + (void)offSnapshot:(NSString *)listenerId;
- (void)onSnapshot:(NSString *)listenerId queryListenOptions:(NSDictionary *) queryListenOptions; - (void)onSnapshot:(NSString *)listenerId queryListenOptions:(NSDictionary *) queryListenOptions;

View File

@ -7,7 +7,7 @@
static NSMutableDictionary *_listeners; static NSMutableDictionary *_listeners;
- (id)initWithPathAndModifiers:(RCTEventEmitter *) emitter - (id)initWithPathAndModifiers:(RCTEventEmitter *) emitter
app:(NSString *) app appDisplayName:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
filters:(NSArray *) filters filters:(NSArray *) filters
orders:(NSArray *) orders orders:(NSArray *) orders
@ -15,7 +15,7 @@ static NSMutableDictionary *_listeners;
self = [super init]; self = [super init];
if (self) { if (self) {
_emitter = emitter; _emitter = emitter;
_app = app; _appDisplayName = appDisplayName;
_path = path; _path = path;
_filters = filters; _filters = filters;
_orders = orders; _orders = orders;
@ -64,7 +64,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
[self handleQuerySnapshotEvent:listenerId querySnapshot:snapshot]; [self handleQuerySnapshotEvent:listenerId querySnapshot:snapshot];
} }
}; };
FIRQueryListenOptions *options = [[FIRQueryListenOptions alloc] init]; FIRQueryListenOptions *options = [[FIRQueryListenOptions alloc] init];
if (queryListenOptions) { if (queryListenOptions) {
if (queryListenOptions[@"includeDocumentMetadataChanges"]) { if (queryListenOptions[@"includeDocumentMetadataChanges"]) {
@ -74,14 +74,14 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
[options includeQueryMetadataChanges:TRUE]; [options includeQueryMetadataChanges:TRUE];
} }
} }
id<FIRListenerRegistration> listener = [_query addSnapshotListenerWithOptions:options listener:listenerBlock]; id<FIRListenerRegistration> listener = [_query addSnapshotListenerWithOptions:options listener:listenerBlock];
_listeners[listenerId] = listener; _listeners[listenerId] = listener;
} }
} }
- (FIRQuery *)buildQuery { - (FIRQuery *)buildQuery {
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:_app]; FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:_appDisplayName];
FIRQuery *query = (FIRQuery*)[firestore collectionWithPath:_path]; FIRQuery *query = (FIRQuery*)[firestore collectionWithPath:_path];
query = [self applyFilters:firestore query:query]; query = [self applyFilters:firestore query:query];
query = [self applyOrders:query]; query = [self applyOrders:query];
@ -152,7 +152,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
- (void)handleQuerySnapshotError:(NSString *)listenerId - (void)handleQuerySnapshotError:(NSString *)listenerId
error:(NSError *)error { error:(NSError *)error {
NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
[event setValue:_app forKey:@"appName"]; [event setValue:_appDisplayName forKey:@"appName"];
[event setValue:_path forKey:@"path"]; [event setValue:_path forKey:@"path"];
[event setValue:listenerId forKey:@"listenerId"]; [event setValue:listenerId forKey:@"listenerId"];
[event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"]; [event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"];
@ -163,7 +163,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
- (void)handleQuerySnapshotEvent:(NSString *)listenerId - (void)handleQuerySnapshotEvent:(NSString *)listenerId
querySnapshot:(FIRQuerySnapshot *)querySnapshot { querySnapshot:(FIRQuerySnapshot *)querySnapshot {
NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
[event setValue:_app forKey:@"appName"]; [event setValue:_appDisplayName forKey:@"appName"];
[event setValue:_path forKey:@"path"]; [event setValue:_path forKey:@"path"];
[event setValue:listenerId forKey:@"listenerId"]; [event setValue:listenerId forKey:@"listenerId"];
[event setValue:[RNFirebaseFirestoreCollectionReference snapshotToDictionary:querySnapshot] forKey:@"querySnapshot"]; [event setValue:[RNFirebaseFirestoreCollectionReference snapshotToDictionary:querySnapshot] forKey:@"querySnapshot"];

View File

@ -13,11 +13,11 @@
@interface RNFirebaseFirestoreDocumentReference : NSObject @interface RNFirebaseFirestoreDocumentReference : NSObject
@property RCTEventEmitter *emitter; @property RCTEventEmitter *emitter;
@property NSString *app; @property NSString *appDisplayName;
@property NSString *path; @property NSString *path;
@property FIRDocumentReference *ref; @property FIRDocumentReference *ref;
- (id)initWithPath:(RCTEventEmitter *)emitter app:(NSString *)app path:(NSString *)path; - (id)initWithPath:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName path:(NSString *)path;
- (void)delete:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; - (void)delete:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; - (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
+ (void)offSnapshot:(NSString *)listenerId; + (void)offSnapshot:(NSString *)listenerId;

View File

@ -7,14 +7,14 @@
static NSMutableDictionary *_listeners; static NSMutableDictionary *_listeners;
- (id)initWithPath:(RCTEventEmitter *)emitter - (id)initWithPath:(RCTEventEmitter *)emitter
app:(NSString *) app appDisplayName:(NSString *) appDisplayName
path:(NSString *) path { path:(NSString *) path {
self = [super init]; self = [super init];
if (self) { if (self) {
_emitter = emitter; _emitter = emitter;
_app = app; _appDisplayName = appDisplayName;
_path = path; _path = path;
_ref = [[RNFirebaseFirestore getFirestoreForApp:_app] documentWithPath:_path]; _ref = [[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] documentWithPath:_path];
} }
// Initialise the static listeners object if required // Initialise the static listeners object if required
if (!_listeners) { if (!_listeners) {
@ -78,7 +78,7 @@ static NSMutableDictionary *_listeners;
options:(NSDictionary *) options options:(NSDictionary *) options
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject { rejecter:(RCTPromiseRejectBlock) reject {
NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_app] jsMap:data]; NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data];
if (options && options[@"merge"]) { if (options && options[@"merge"]) {
[_ref setData:dictionary options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) { [_ref setData:dictionary options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
@ -93,7 +93,7 @@ static NSMutableDictionary *_listeners;
- (void)update:(NSDictionary *) data - (void)update:(NSDictionary *) data
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject { rejecter:(RCTPromiseRejectBlock) reject {
NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_app] jsMap:data]; NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data];
[_ref updateData:dictionary completion:^(NSError * _Nullable error) { [_ref updateData:dictionary completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}]; }];
@ -131,7 +131,7 @@ static NSMutableDictionary *_listeners;
- (void)handleDocumentSnapshotError:(NSString *)listenerId - (void)handleDocumentSnapshotError:(NSString *)listenerId
error:(NSError *)error { error:(NSError *)error {
NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
[event setValue:_app forKey:@"appName"]; [event setValue:_appDisplayName forKey:@"appName"];
[event setValue:_path forKey:@"path"]; [event setValue:_path forKey:@"path"];
[event setValue:listenerId forKey:@"listenerId"]; [event setValue:listenerId forKey:@"listenerId"];
[event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"]; [event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"];
@ -142,7 +142,7 @@ static NSMutableDictionary *_listeners;
- (void)handleDocumentSnapshotEvent:(NSString *)listenerId - (void)handleDocumentSnapshotEvent:(NSString *)listenerId
documentSnapshot:(FIRDocumentSnapshot *)documentSnapshot { documentSnapshot:(FIRDocumentSnapshot *)documentSnapshot {
NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
[event setValue:_app forKey:@"appName"]; [event setValue:_appDisplayName forKey:@"appName"];
[event setValue:_path forKey:@"path"]; [event setValue:_path forKey:@"path"];
[event setValue:listenerId forKey:@"listenerId"]; [event setValue:listenerId forKey:@"listenerId"];
[event setValue:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:documentSnapshot] forKey:@"documentSnapshot"]; [event setValue:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:documentSnapshot] forKey:@"documentSnapshot"];

View File

@ -23,11 +23,11 @@ RCT_EXPORT_MODULE(RNFirebaseStorage);
@url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete
@param NSString path @param NSString path
*/ */
RCT_EXPORT_METHOD(delete:(NSString *) appName RCT_EXPORT_METHOD(delete:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path appName:appName]; FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
[fileRef deleteWithCompletion:^(NSError *_Nullable error) { [fileRef deleteWithCompletion:^(NSError *_Nullable error) {
if (error != nil) { if (error != nil) {
@ -44,11 +44,11 @@ RCT_EXPORT_METHOD(delete:(NSString *) appName
@url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getDownloadURL @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getDownloadURL
@param NSString path @param NSString path
*/ */
RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appName RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path appName:appName]; FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
[fileRef downloadURLWithCompletion:^(NSURL *_Nullable URL, NSError *_Nullable error) { [fileRef downloadURLWithCompletion:^(NSURL *_Nullable URL, NSError *_Nullable error) {
if (error != nil) { if (error != nil) {
@ -65,11 +65,11 @@ RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appName
@url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getMetadata @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getMetadata
@param NSString path @param NSString path
*/ */
RCT_EXPORT_METHOD(getMetadata:(NSString *) appName RCT_EXPORT_METHOD(getMetadata:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path appName:appName]; FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
[fileRef metadataWithCompletion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) { [fileRef metadataWithCompletion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
if (error != nil) { if (error != nil) {
@ -87,12 +87,12 @@ RCT_EXPORT_METHOD(getMetadata:(NSString *) appName
@param NSString path @param NSString path
@param NSDictionary metadata @param NSDictionary metadata
*/ */
RCT_EXPORT_METHOD(updateMetadata:(NSString *) appName RCT_EXPORT_METHOD(updateMetadata:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
metadata:(NSDictionary *) metadata metadata:(NSDictionary *) metadata
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path appName:appName]; FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata]; FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
[fileRef updateMetadata:firmetadata completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) { [fileRef updateMetadata:firmetadata completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
@ -111,12 +111,12 @@ RCT_EXPORT_METHOD(updateMetadata:(NSString *) appName
@param NSString path @param NSString path
@param NSString localPath @param NSString localPath
*/ */
RCT_EXPORT_METHOD(downloadFile:(NSString *) appName RCT_EXPORT_METHOD(downloadFile:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
localPath:(NSString *) localPath localPath:(NSString *) localPath
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) reject) {
FIRStorageReference *fileRef = [self getReference:path appName:appName]; FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
NSURL *localFile = [NSURL fileURLWithPath:localPath]; NSURL *localFile = [NSURL fileURLWithPath:localPath];
FIRStorageDownloadTask *downloadTask = [fileRef writeToFile:localFile]; FIRStorageDownloadTask *downloadTask = [fileRef writeToFile:localFile];
@ -124,25 +124,25 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appName
[downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) { [downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
// download resumed, also fires when the upload starts // download resumed, also fires when the upload starts
NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot]; NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}]; }];
[downloadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) { [downloadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) {
// download paused // download paused
NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot]; NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}]; }];
[downloadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) { [downloadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) {
// download reported progress // download reported progress
NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot]; NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}]; }];
[downloadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) { [downloadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) {
// download completed successfully // download completed successfully
NSDictionary *resp = [self getDownloadTaskAsDictionary:snapshot]; NSDictionary *resp = [self getDownloadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_DOWNLOAD_SUCCESS props:resp]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_DOWNLOAD_SUCCESS props:resp];
resolve(resp); resolve(resp);
}]; }];
@ -161,9 +161,10 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appName
@url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxDownloadRetryTime @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxDownloadRetryTime
@param NSNumber milliseconds @param NSNumber milliseconds
*/ */
RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appName RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appDisplayName
milliseconds:(NSNumber *) milliseconds) { milliseconds:(NSNumber *) milliseconds) {
[[FIRStorage storageForApp:[FIRApp appNamed:appName]] setMaxDownloadRetryTime:[milliseconds doubleValue]]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRStorage storageForApp:firApp] setMaxDownloadRetryTime:[milliseconds doubleValue]];
} }
/** /**
@ -172,9 +173,10 @@ RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appName
@url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxOperationRetryTime @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxOperationRetryTime
@param NSNumber milliseconds @param NSNumber milliseconds
*/ */
RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appName RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appDisplayName
milliseconds:(NSNumber *) milliseconds) { milliseconds:(NSNumber *) milliseconds) {
[[FIRStorage storageForApp:[FIRApp appNamed:appName]] setMaxOperationRetryTime:[milliseconds doubleValue]]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRStorage storageForApp:firApp] setMaxOperationRetryTime:[milliseconds doubleValue]];
} }
/** /**
@ -182,9 +184,10 @@ RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appName
@url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxUploadRetryTime @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxUploadRetryTime
*/ */
RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appName RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appDisplayName
milliseconds:(NSNumber *) milliseconds) { milliseconds:(NSNumber *) milliseconds) {
[[FIRStorage storageForApp:[FIRApp appNamed:appName]] setMaxUploadRetryTime:[milliseconds doubleValue]]; FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
[[FIRStorage storageForApp:firApp] setMaxUploadRetryTime:[milliseconds doubleValue]];
} }
/** /**
@ -195,7 +198,7 @@ RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appName
@param NSString localPath @param NSString localPath
@param NSDictionary metadata @param NSDictionary metadata
*/ */
RCT_EXPORT_METHOD(putFile:(NSString *) appName RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
path:(NSString *) path path:(NSString *) path
localPath:(NSString *) localPath localPath:(NSString *) localPath
metadata:(NSDictionary *) metadata metadata:(NSDictionary *) metadata
@ -224,7 +227,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
if (info[PHImageErrorKey] == nil) { if (info[PHImageErrorKey] == nil) {
if (UTTypeConformsTo((__bridge CFStringRef)dataUTI, kUTTypeJPEG)) { if (UTTypeConformsTo((__bridge CFStringRef)dataUTI, kUTTypeJPEG)) {
firmetadata.contentType = [self utiToMimeType:dataUTI]; firmetadata.contentType = [self utiToMimeType:dataUTI];
[self uploadData:appName data:imageData firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; [self uploadData:appDisplayName data:imageData firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
} else { } else {
// if the image UTI is not JPEG then convert to JPEG, e.g. HEI // if the image UTI is not JPEG then convert to JPEG, e.g. HEI
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
@ -236,7 +239,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
CGImageDestinationFinalize(destination); CGImageDestinationFinalize(destination);
// Manually set mimetype to JPEG // Manually set mimetype to JPEG
firmetadata.contentType = @"image/jpeg"; firmetadata.contentType = @"image/jpeg";
[self uploadData:appName data:[NSData dataWithData:imageDataJPEG] firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; [self uploadData:appDisplayName data:[NSData dataWithData:imageDataJPEG] firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
} }
} else { } else {
reject(@"storage/request-image-data-failed", @"Could not obtain image data for the specified file.", nil); reject(@"storage/request-image-data-failed", @"Could not obtain image data for the specified file.", nil);
@ -260,7 +263,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
[exportSession exportAsynchronouslyWithCompletionHandler:^{ [exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) { if (exportSession.status == AVAssetExportSessionStatusCompleted) {
firmetadata.contentType = [self utiToMimeType:exportSession.outputFileType]; firmetadata.contentType = [self utiToMimeType:exportSession.outputFileType];
[self uploadFile:appName url:tempUrl firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; [self uploadFile:appDisplayName url:tempUrl firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
// we're not cleaning up the temporary file at the moment, just relying on the OS to do that in it's own time - todo? // we're not cleaning up the temporary file at the moment, just relying on the OS to do that in it's own time - todo?
} else { } else {
reject(@"storage/temporary-file-failure", @"Unable to create temporary file for upload.", nil); reject(@"storage/temporary-file-failure", @"Unable to create temporary file for upload.", nil);
@ -274,7 +277,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
} else { } else {
// TODO: Content type for file? // TODO: Content type for file?
NSData *data = [[NSFileManager defaultManager] contentsAtPath:localPath]; NSData *data = [[NSFileManager defaultManager] contentsAtPath:localPath];
[self uploadData:appName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; [self uploadData:appDisplayName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
} }
} }
@ -288,42 +291,42 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)dataUTI, kUTTagClassMIMEType); return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)dataUTI, kUTTagClassMIMEType);
} }
- (void)uploadFile:(NSString *)appName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { - (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
FIRStorageReference *fileRef = [self getReference:path appName:appName]; FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
FIRStorageUploadTask *uploadTask = [fileRef putFile:url metadata:firmetadata]; FIRStorageUploadTask *uploadTask = [fileRef putFile:url metadata:firmetadata];
[self addUploadObservers:appName uploadTask:uploadTask path:path resolver:resolve rejecter:reject]; [self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];
} }
- (void)uploadData:(NSString *)appName data:(NSData *)data firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { - (void)uploadData:(NSString *)appDisplayName data:(NSData *)data firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
FIRStorageReference *fileRef = [self getReference:path appName:appName]; FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
FIRStorageUploadTask *uploadTask = [fileRef putData:data metadata:firmetadata]; FIRStorageUploadTask *uploadTask = [fileRef putData:data metadata:firmetadata];
[self addUploadObservers:appName uploadTask:uploadTask path:path resolver:resolve rejecter:reject]; [self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject];
} }
- (void)addUploadObservers:(NSString *)appName uploadTask:(FIRStorageUploadTask *)uploadTask path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { - (void)addUploadObservers:(NSString *)appDisplayName uploadTask:(FIRStorageUploadTask *)uploadTask path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
// listen for state changes, errors, and completion of the upload. // listen for state changes, errors, and completion of the upload.
[uploadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) { [uploadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload resumed, also fires when the upload starts // upload resumed, also fires when the upload starts
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot]; NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}]; }];
[uploadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) { [uploadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload paused // upload paused
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot]; NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}]; }];
[uploadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) { [uploadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload reported progress // upload reported progress
NSDictionary *event = [self getUploadTaskAsDictionary:snapshot]; NSDictionary *event = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event];
}]; }];
[uploadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) { [uploadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) {
// upload completed successfully // upload completed successfully
NSDictionary *resp = [self getUploadTaskAsDictionary:snapshot]; NSDictionary *resp = [self getUploadTaskAsDictionary:snapshot];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:resp]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:resp];
[self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp]; [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp];
resolve(resp); resolve(resp);
}]; }];
@ -335,12 +338,13 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
} }
- (FIRStorageReference *)getReference:(NSString *)path - (FIRStorageReference *)getReference:(NSString *)path
appName:(NSString *)appName { appDisplayName:(NSString *)appDisplayName {
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
if ([path hasPrefix:@"url::"]) { if ([path hasPrefix:@"url::"]) {
NSString *url = [path substringFromIndex:5]; NSString *url = [path substringFromIndex:5];
return [[FIRStorage storageForApp:[FIRApp appNamed:appName]] referenceForURL:url]; return [[FIRStorage storageForApp:firApp] referenceForURL:url];
} else { } else {
return [[FIRStorage storageForApp:[FIRApp appNamed:appName]] referenceWithPath:path]; return [[FIRStorage storageForApp:firApp] referenceWithPath:path];
} }
} }
@ -387,13 +391,13 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
return @[STORAGE_EVENT, STORAGE_ERROR]; return @[STORAGE_EVENT, STORAGE_ERROR];
} }
- (void)sendJSError:(NSString *)appName error:(NSError *)error path:(NSString *)path { - (void)sendJSError:(NSString *)appDisplayName error:(NSError *)error path:(NSString *)path {
NSDictionary *evt = @{@"path": path, @"message": [error debugDescription]}; NSDictionary *evt = @{@"path": path, @"message": [error debugDescription]};
[self sendJSEvent:appName type:STORAGE_ERROR path:path title:STORAGE_ERROR props:evt]; [self sendJSEvent:appDisplayName type:STORAGE_ERROR path:path title:STORAGE_ERROR props:evt];
} }
- (void)sendJSEvent:(NSString *)appName type:(NSString *)type path:(NSString *)path title:(NSString *)title props:(NSDictionary *)props { - (void)sendJSEvent:(NSString *)appDisplayName type:(NSString *)type path:(NSString *)path title:(NSString *)title props:(NSDictionary *)props {
[RNFirebaseUtil sendJSEvent:self name:type body:@{@"eventName": title, @"appName": appName, @"path": path, @"body": props}]; [RNFirebaseUtil sendJSEvent:self name:type body:@{@"eventName": title, @"appName": appDisplayName, @"path": path, @"body": props}];
} }
/** /**

View File

@ -1,8 +1,8 @@
/** /**
* @flow * @flow
*/ */
import Firebase from './modules/core/firebase'; import firebase from './modules/core/firebase';
export const AdMob = require('./modules/admob'); export type { default as User } from './modules/auth/User';
export default Firebase; export default firebase;

View File

@ -1,6 +1,7 @@
import { NativeModules, Platform } from 'react-native'; import { NativeModules, Platform } from 'react-native';
import { statics } from './'; import { statics } from './';
import AdRequest from './AdRequest'; import AdRequest from './AdRequest';
import { SharedEventEmitter } from '../../utils/events';
import { nativeToJSError } from '../../utils'; import { nativeToJSError } from '../../utils';
const FirebaseAdMob = NativeModules.RNFirebaseAdMob; const FirebaseAdMob = NativeModules.RNFirebaseAdMob;
@ -23,8 +24,8 @@ export default class Interstitial {
this.admob = admob; this.admob = admob;
this.adUnit = adUnit; this.adUnit = adUnit;
this.loaded = false; this.loaded = false;
this.admob.removeAllListeners(`interstitial_${adUnit}`); SharedEventEmitter.removeAllListeners(`interstitial_${adUnit}`);
this.admob.on(`interstitial_${adUnit}`, this._onInterstitialEvent); SharedEventEmitter.addListener(`interstitial_${adUnit}`, this._onInterstitialEvent);
} }
/** /**
@ -48,8 +49,8 @@ export default class Interstitial {
default: default:
} }
this.admob.emit(eventType, emitData); SharedEventEmitter.emit(eventType, emitData);
this.admob.emit(`interstitial:${this.adUnit}:*`, emitData); SharedEventEmitter.emit(`interstitial:${this.adUnit}:*`, emitData);
}; };
/** /**
@ -97,7 +98,7 @@ export default class Interstitial {
return null; return null;
} }
const sub = this.admob.on(`interstitial:${this.adUnit}:${eventType}`, listenerCb); const sub = SharedEventEmitter.addListener(`interstitial:${this.adUnit}:${eventType}`, listenerCb);
subscriptions.push(sub); subscriptions.push(sub);
return sub; return sub;
} }

View File

@ -1,6 +1,7 @@
import { NativeModules } from 'react-native'; import { NativeModules } from 'react-native';
import { statics } from './'; import { statics } from './';
import AdRequest from './AdRequest'; import AdRequest from './AdRequest';
import { SharedEventEmitter } from '../../utils/events';
import { nativeToJSError } from '../../utils'; import { nativeToJSError } from '../../utils';
const FirebaseAdMob = NativeModules.RNFirebaseAdMob; const FirebaseAdMob = NativeModules.RNFirebaseAdMob;
@ -18,8 +19,8 @@ export default class RewardedVideo {
this.admob = admob; this.admob = admob;
this.adUnit = adUnit; this.adUnit = adUnit;
this.loaded = false; this.loaded = false;
this.admob.removeAllListeners(`rewarded_video_${adUnit}`); SharedEventEmitter.removeAllListeners(`rewarded_video_${adUnit}`);
this.admob.on(`rewarded_video_${adUnit}`, this._onRewardedVideoEvent); SharedEventEmitter.addListener(`rewarded_video_${adUnit}`, this._onRewardedVideoEvent);
} }
/** /**
@ -43,8 +44,8 @@ export default class RewardedVideo {
default: default:
} }
this.admob.emit(eventType, emitData); SharedEventEmitter.emit(eventType, emitData);
this.admob.emit(`rewarded_video:${this.adUnit}:*`, emitData); SharedEventEmitter.emit(`rewarded_video:${this.adUnit}:*`, emitData);
}; };
/** /**
@ -97,7 +98,7 @@ export default class RewardedVideo {
return null; return null;
} }
const sub = this.admob.on(`rewarded_video:${this.adUnit}:${eventType}`, listenerCb); const sub = SharedEventEmitter.addListener(`rewarded_video:${this.adUnit}:${eventType}`, listenerCb);
subscriptions.push(sub); subscriptions.push(sub);
return sub; return sub;
} }

View File

@ -2,7 +2,9 @@
* @flow * @flow
* AdMob representation wrapper * AdMob representation wrapper
*/ */
import ModuleBase from './../../utils/ModuleBase'; import { SharedEventEmitter } from '../../utils/events';
import { getLogger } from '../../utils/log';
import ModuleBase from '../../utils/ModuleBase';
import Interstitial from './Interstitial'; import Interstitial from './Interstitial';
import RewardedVideo from './RewardedVideo'; import RewardedVideo from './RewardedVideo';
@ -24,48 +26,57 @@ type NativeEvent = {
type: string, type: string,
} }
export default class AdMob extends ModuleBase { const NATIVE_EVENTS = [
static _NAMESPACE = 'admob'; 'interstitial_event',
static _NATIVE_MODULE = 'RNFirebaseAdMob'; 'rewarded_video_event',
];
export const MODULE_NAME = 'RNFirebaseAdmob';
export const NAMESPACE = 'admob';
export default class AdMob extends ModuleBase {
_appId: ?string; _appId: ?string;
_initialized: boolean; _initialized: boolean;
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options, true); super(firebaseApp, options, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
this._initialized = false; this._initialized = false;
this._appId = null; this._appId = null;
this._eventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this)); SharedEventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this));
this._eventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this)); SharedEventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this));
} }
_onInterstitialEvent(event: NativeEvent): void { _onInterstitialEvent(event: NativeEvent): void {
const { adUnit } = event; const { adUnit } = event;
const jsEventType = `interstitial_${adUnit}`; const jsEventType = `interstitial_${adUnit}`;
if (!this.hasListeners(jsEventType)) { if (!SharedEventEmitter.hasListeners(jsEventType)) {
// TODO // TODO
} }
this.emit(jsEventType, event); SharedEventEmitter.emit(jsEventType, event);
} }
_onRewardedVideoEvent(event: NativeEvent): void { _onRewardedVideoEvent(event: NativeEvent): void {
const { adUnit } = event; const { adUnit } = event;
const jsEventType = `rewarded_video_${adUnit}`; const jsEventType = `rewarded_video_${adUnit}`;
if (!this.hasListeners(jsEventType)) { if (!SharedEventEmitter.hasListeners(jsEventType)) {
// TODO // TODO
} }
this.emit(jsEventType, event); SharedEventEmitter.emit(jsEventType, event);
} }
initialize(appId: string): void { initialize(appId: string): void {
if (this._initialized) { if (this._initialized) {
this.log.warn('AdMob has already been initialized!'); getLogger(this).warn('AdMob has already been initialized!');
} else { } else {
this._initialized = true; this._initialized = true;
this._appId = appId; this._appId = appId;
@ -75,9 +86,9 @@ export default class AdMob extends ModuleBase {
openDebugMenu(): void { openDebugMenu(): void {
if (!this._initialized) { if (!this._initialized) {
this.log.warn('AdMob needs to be initialized before opening the dev menu!'); getLogger(this).warn('AdMob needs to be initialized before opening the dev menu!');
} else { } else {
this.log.info('Opening debug menu'); getLogger(this).info('Opening debug menu');
this._native.openDebugMenu(this._appId); this._native.openDebugMenu(this._appId);
} }
} }

View File

@ -24,12 +24,15 @@ const ReservedEventNames = [
'user_engagement', 'user_engagement',
]; ];
export default class Analytics extends ModuleBase { export const MODULE_NAME = 'RNFirebaseAnalytics';
static _NAMESPACE = 'analytics'; export const NAMESPACE = 'analytics';
static _NATIVE_MODULE = 'RNFirebaseAnalytics';
export default class Analytics extends ModuleBase {
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options); super(firebaseApp, options, {
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
} }
/** /**

View File

@ -1,5 +1,6 @@
// @flow // @flow
import INTERNALS from '../../utils/internals'; import INTERNALS from '../../utils/internals';
import { SharedEventEmitter } from '../../utils/events';
import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from './../../utils'; import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from './../../utils';
import type Auth from './'; import type Auth from './';
@ -92,7 +93,7 @@ export default class PhoneAuthListener {
for (let i = 0, len = events.length; i < len; i++) { for (let i = 0, len = events.length; i < len; i++) {
const type = events[i]; const type = events[i];
this._auth.once(this._internalEvents[type], this[`_${type}Handler`].bind(this)); SharedEventEmitter.once(this._internalEvents[type], this[`_${type}Handler`].bind(this));
} }
} }
@ -102,7 +103,7 @@ export default class PhoneAuthListener {
* @private * @private
*/ */
_addUserObserver(observer) { _addUserObserver(observer) {
this._auth.on(this._publicEvents.event, observer); SharedEventEmitter.addListener(this._publicEvents.event, observer);
} }
/** /**
@ -111,7 +112,7 @@ export default class PhoneAuthListener {
* @private * @private
*/ */
_emitToObservers(snapshot: PhoneAuthSnapshot) { _emitToObservers(snapshot: PhoneAuthSnapshot) {
this._auth.emit(this._publicEvents.event, snapshot); SharedEventEmitter.emit(this._publicEvents.event, snapshot);
} }
/** /**
@ -122,7 +123,7 @@ export default class PhoneAuthListener {
_emitToErrorCb(snapshot) { _emitToErrorCb(snapshot) {
const error = snapshot.error; const error = snapshot.error;
if (this._reject) this._reject(error); if (this._reject) this._reject(error);
this._auth.emit(this._publicEvents.error, error); SharedEventEmitter.emit(this._publicEvents.error, error);
} }
/** /**
@ -132,7 +133,7 @@ export default class PhoneAuthListener {
*/ */
_emitToSuccessCb(snapshot) { _emitToSuccessCb(snapshot) {
if (this._resolve) this._resolve(snapshot); if (this._resolve) this._resolve(snapshot);
this._auth.emit(this._publicEvents.success, snapshot); SharedEventEmitter.emit(this._publicEvents.success, snapshot);
} }
/** /**
@ -143,12 +144,12 @@ export default class PhoneAuthListener {
setTimeout(() => { // move to next event loop - not sure if needed setTimeout(() => { // move to next event loop - not sure if needed
// internal listeners // internal listeners
Object.values(this._internalEvents).forEach((event) => { Object.values(this._internalEvents).forEach((event) => {
this._auth.removeAllListeners(event); SharedEventEmitter.removeAllListeners(event);
}); });
// user observer listeners // user observer listeners
Object.values(this._publicEvents).forEach((publicEvent) => { Object.values(this._publicEvents).forEach((publicEvent) => {
this._auth.removeAllListeners(publicEvent); SharedEventEmitter.removeAllListeners(publicEvent);
}); });
}, 0); }, 0);
} }
@ -279,11 +280,11 @@ export default class PhoneAuthListener {
this._addUserObserver(observer); this._addUserObserver(observer);
if (isFunction(errorCb)) { if (isFunction(errorCb)) {
this._auth.once(this._publicEvents.error, errorCb); SharedEventEmitter.once(this._publicEvents.error, errorCb);
} }
if (isFunction(successCb)) { if (isFunction(successCb)) {
this._auth.once(this._publicEvents.success, successCb); SharedEventEmitter.once(this._publicEvents.success, successCb);
} }
return this; return this;

View File

@ -4,6 +4,8 @@
*/ */
import User from './User'; import User from './User';
import ModuleBase from '../../utils/ModuleBase'; import ModuleBase from '../../utils/ModuleBase';
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
import { getLogger } from '../../utils/log';
import INTERNALS from '../../utils/internals'; import INTERNALS from '../../utils/internals';
import ConfirmationResult from './ConfirmationResult'; import ConfirmationResult from './ConfirmationResult';
@ -25,36 +27,45 @@ type AuthResult = {
user: Object|null user: Object|null
} | null; } | null;
export default class Auth extends ModuleBase { const NATIVE_EVENTS = [
static _NAMESPACE = 'auth'; 'auth_state_changed',
static _NATIVE_MODULE = 'RNFirebaseAuth'; 'phone_auth_state_changed',
];
export const MODULE_NAME = 'RNFirebaseAuth';
export const NAMESPACE = 'auth';
export default class Auth extends ModuleBase {
_authResult: AuthResult | null; _authResult: AuthResult | null;
_user: User | null; _user: User | null;
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options, true); super(firebaseApp, options, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
this._user = null; this._user = null;
this._authResult = null; this._authResult = null;
this.addListener( SharedEventEmitter.addListener(
// sub to internal native event - this fans out to // sub to internal native event - this fans out to
// public event name: onAuthStateChanged // public event name: onAuthStateChanged
super._getAppEventName('auth_state_changed'), getAppEventName(this, 'auth_state_changed'),
this._onInternalAuthStateChanged.bind(this), this._onInternalAuthStateChanged.bind(this),
); );
this.addListener( SharedEventEmitter.addListener(
// sub to internal native event - this fans out to // sub to internal native event - this fans out to
// public events based on event.type // public events based on event.type
super._getAppEventName('phone_auth_state_changed'), getAppEventName(this, 'phone_auth_state_changed'),
this._onInternalPhoneAuthStateChanged.bind(this), this._onInternalPhoneAuthStateChanged.bind(this),
); );
this.addListener( SharedEventEmitter.addListener(
// sub to internal native event - this fans out to // sub to internal native event - this fans out to
// public event name: onIdTokenChanged // public event name: onIdTokenChanged
super._getAppEventName('auth_id_token_changed'), getAppEventName(this, 'auth_id_token_changed'),
this._onInternalIdTokenChanged.bind(this), this._onInternalIdTokenChanged.bind(this),
); );
@ -69,13 +80,13 @@ export default class Auth extends ModuleBase {
*/ */
_onInternalPhoneAuthStateChanged(event: Object) { _onInternalPhoneAuthStateChanged(event: Object) {
const eventKey = `phone:auth:${event.requestKey}:${event.type}`; const eventKey = `phone:auth:${event.requestKey}:${event.type}`;
this.emit(eventKey, event.state); SharedEventEmitter.emit(eventKey, event.state);
} }
_setAuthState(auth: AuthResult) { _setAuthState(auth: AuthResult) {
this._authResult = auth; this._authResult = auth;
this._user = auth && auth.user ? new User(this, auth.user) : null; this._user = auth && auth.user ? new User(this, auth.user) : null;
this.emit(this._getAppEventName('onUserChanged'), this._user); SharedEventEmitter.emit(getAppEventName(this, 'onUserChanged'), this._user);
} }
/** /**
@ -85,7 +96,7 @@ export default class Auth extends ModuleBase {
*/ */
_onInternalAuthStateChanged(auth: AuthResult) { _onInternalAuthStateChanged(auth: AuthResult) {
this._setAuthState(auth); this._setAuthState(auth);
this.emit(this._getAppEventName('onAuthStateChanged'), this._user); SharedEventEmitter.emit(getAppEventName(this, 'onAuthStateChanged'), this._user);
} }
/** /**
@ -96,7 +107,7 @@ export default class Auth extends ModuleBase {
*/ */
_onInternalIdTokenChanged(auth: AuthResult) { _onInternalIdTokenChanged(auth: AuthResult) {
this._setAuthState(auth); this._setAuthState(auth);
this.emit(this._getAppEventName('onIdTokenChanged'), this._user); SharedEventEmitter.emit(getAppEventName(this, 'onIdTokenChanged'), this._user);
} }
/** /**
@ -129,8 +140,8 @@ export default class Auth extends ModuleBase {
* @param listener * @param listener
*/ */
onAuthStateChanged(listener: Function) { onAuthStateChanged(listener: Function) {
this.log.info('Creating onAuthStateChanged listener'); getLogger(this).info('Creating onAuthStateChanged listener');
this.on(this._getAppEventName('onAuthStateChanged'), listener); SharedEventEmitter.addListener(getAppEventName(this, 'onAuthStateChanged'), listener);
if (this._authResult) listener(this._user || null); if (this._authResult) listener(this._user || null);
return this._offAuthStateChanged.bind(this, listener); return this._offAuthStateChanged.bind(this, listener);
} }
@ -140,8 +151,8 @@ export default class Auth extends ModuleBase {
* @param listener * @param listener
*/ */
_offAuthStateChanged(listener: Function) { _offAuthStateChanged(listener: Function) {
this.log.info('Removing onAuthStateChanged listener'); getLogger(this).info('Removing onAuthStateChanged listener');
this.removeListener(this._getAppEventName('onAuthStateChanged'), listener); SharedEventEmitter.removeListener(getAppEventName(this, 'onAuthStateChanged'), listener);
} }
/** /**
@ -149,8 +160,8 @@ export default class Auth extends ModuleBase {
* @param listener * @param listener
*/ */
onIdTokenChanged(listener: Function) { onIdTokenChanged(listener: Function) {
this.log.info('Creating onIdTokenChanged listener'); getLogger(this).info('Creating onIdTokenChanged listener');
this.on(this._getAppEventName('onIdTokenChanged'), listener); SharedEventEmitter.addListener(getAppEventName(this, 'onIdTokenChanged'), listener);
if (this._authResult) listener(this._user || null); if (this._authResult) listener(this._user || null);
return this._offIdTokenChanged.bind(this, listener); return this._offIdTokenChanged.bind(this, listener);
} }
@ -160,8 +171,8 @@ export default class Auth extends ModuleBase {
* @param listener * @param listener
*/ */
_offIdTokenChanged(listener: Function) { _offIdTokenChanged(listener: Function) {
this.log.info('Removing onIdTokenChanged listener'); getLogger(this).info('Removing onIdTokenChanged listener');
this.removeListener(this._getAppEventName('onIdTokenChanged'), listener); SharedEventEmitter.removeListener(getAppEventName(this, 'onIdTokenChanged'), listener);
} }
/** /**
@ -169,8 +180,8 @@ export default class Auth extends ModuleBase {
* @param listener * @param listener
*/ */
onUserChanged(listener: Function) { onUserChanged(listener: Function) {
this.log.info('Creating onUserChanged listener'); getLogger(this).info('Creating onUserChanged listener');
this.on(this._getAppEventName('onUserChanged'), listener); SharedEventEmitter.addListener(getAppEventName(this, 'onUserChanged'), listener);
if (this._authResult) listener(this._user || null); if (this._authResult) listener(this._user || null);
return this._offUserChanged.bind(this, listener); return this._offUserChanged.bind(this, listener);
} }
@ -180,8 +191,8 @@ export default class Auth extends ModuleBase {
* @param listener * @param listener
*/ */
_offUserChanged(listener: Function) { _offUserChanged(listener: Function) {
this.log.info('Removing onUserChanged listener'); getLogger(this).info('Removing onUserChanged listener');
this.removeListener(this._getAppEventName('onUserChanged'), listener); SharedEventEmitter.removeListener(getAppEventName(this, 'onUserChanged'), listener);
} }
/** /**
@ -339,23 +350,23 @@ export default class Auth extends ModuleBase {
*/ */
getRedirectResult() { getRedirectResult() {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'getRedirectResult')); throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'getRedirectResult'));
} }
setPersistence() { setPersistence() {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'setPersistence')); throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'setPersistence'));
} }
signInAndRetrieveDataWithCredential() { signInAndRetrieveDataWithCredential() {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInAndRetrieveDataWithCredential')); throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInAndRetrieveDataWithCredential'));
} }
signInWithPopup() { signInWithPopup() {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInWithPopup')); throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInWithPopup'));
} }
signInWithRedirect() { signInWithRedirect() {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInWithRedirect')); throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInWithRedirect'));
} }
} }

View File

@ -2,6 +2,7 @@
* @flow * @flow
* Remote Config representation wrapper * Remote Config representation wrapper
*/ */
import { getLogger } from '../../utils/log';
import ModuleBase from './../../utils/ModuleBase'; import ModuleBase from './../../utils/ModuleBase';
import type FirebaseApp from '../core/firebase-app'; import type FirebaseApp from '../core/firebase-app';
@ -14,17 +15,20 @@ type NativeValue = {
source: 'remoteConfigSourceRemote' | 'remoteConfigSourceDefault' | ' remoteConfigSourceStatic', source: 'remoteConfigSourceRemote' | 'remoteConfigSourceDefault' | ' remoteConfigSourceStatic',
} }
export const MODULE_NAME = 'RNFirebaseRemoteConfig';
export const NAMESPACE = 'config';
/** /**
* @class Config * @class Config
*/ */
export default class RemoteConfig extends ModuleBase { export default class RemoteConfig extends ModuleBase {
static _NAMESPACE = 'config';
static _NATIVE_MODULE = 'RNFirebaseRemoteConfig';
_developerModeEnabled: boolean; _developerModeEnabled: boolean;
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options); super(firebaseApp, options, {
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
this._developerModeEnabled = false; this._developerModeEnabled = false;
} }
@ -51,7 +55,7 @@ export default class RemoteConfig extends ModuleBase {
*/ */
enableDeveloperMode() { enableDeveloperMode() {
if (!this._developerModeEnabled) { if (!this._developerModeEnabled) {
this.log.debug('Enabled developer mode'); getLogger(this).debug('Enabled developer mode');
this._native.enableDeveloperMode(); this._native.enableDeveloperMode();
this._developerModeEnabled = true; this._developerModeEnabled = true;
} }
@ -64,10 +68,10 @@ export default class RemoteConfig extends ModuleBase {
*/ */
fetch(expiration?: number) { fetch(expiration?: number) {
if (expiration !== undefined) { if (expiration !== undefined) {
this.log.debug(`Fetching remote config data with expiration ${expiration.toString()}`); getLogger(this).debug(`Fetching remote config data with expiration ${expiration.toString()}`);
return this._native.fetchWithExpirationDuration(expiration); return this._native.fetchWithExpirationDuration(expiration);
} }
this.log.debug('Fetching remote config data'); getLogger(this).debug('Fetching remote config data');
return this._native.fetch(); return this._native.fetch();
} }
@ -78,7 +82,7 @@ export default class RemoteConfig extends ModuleBase {
* rejects if no Fetched Config was found, or the Fetched Config was already activated. * rejects if no Fetched Config was found, or the Fetched Config was already activated.
*/ */
activateFetched() { activateFetched() {
this.log.debug('Activating remote config'); getLogger(this).debug('Activating remote config');
return this._native.activateFetched(); return this._native.activateFetched();
} }

View File

@ -3,41 +3,27 @@
*/ */
import { NativeModules } from 'react-native'; import { NativeModules } from 'react-native';
import APPS from '../../utils/apps';
import { SharedEventEmitter } from '../../utils/events';
import INTERNALS from '../../utils/internals'; import INTERNALS from '../../utils/internals';
import { isObject, isAndroid } from '../../utils'; import { isObject } from '../../utils';
import AdMob, { statics as AdMobStatics } from '../admob'; import AdMob, { NAMESPACE as AdmobNamespace } from '../admob';
import Auth, { statics as AuthStatics } from '../auth'; import Auth, { NAMESPACE as AuthNamespace } from '../auth';
import Analytics, { statics as AnalyticsStatics } from '../analytics'; import Analytics, { NAMESPACE as AnalyticsNamespace } from '../analytics';
import Config, { statics as ConfigStatics } from '../config'; import Config, { NAMESPACE as ConfigNamespace } from '../config';
import Crash, { statics as CrashStatics } from '../crash'; import Crash, { NAMESPACE as CrashNamespace } from '../crash';
import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics'; import Crashlytics, { NAMESPACE as CrashlyticsNamespace } from '../fabric/crashlytics';
import Database, { statics as DatabaseStatics } from '../database'; import Database, { NAMESPACE as DatabaseNamespace } from '../database';
import Firestore, { statics as FirestoreStatics } from '../firestore'; import Firestore, { NAMESPACE as FirestoreNamespace } from '../firestore';
import Links, { statics as LinksStatics } from '../links'; import Links, { NAMESPACE as LinksNamespace } from '../links';
import Messaging, { statics as MessagingStatics } from '../messaging'; import Messaging, { NAMESPACE as MessagingNamespace } from '../messaging';
import Performance, { statics as PerformanceStatics } from '../perf'; import Performance, { NAMESPACE as PerfNamespace } from '../perf';
import Storage, { statics as StorageStatics } from '../storage'; import Storage, { NAMESPACE as StorageNamespace } from '../storage';
import Utils, { statics as UtilsStatics } from '../utils'; import Utils, { NAMESPACE as UtilsNamespace } from '../utils';
import type { import type {
AdMobModule,
AnalyticsModule,
AuthModule,
ConfigModule,
CrashModule,
DatabaseModule,
FabricModule,
FirebaseModule,
FirebaseModuleAndStatics,
FirebaseOptions, FirebaseOptions,
FirebaseStatics,
FirestoreModule,
LinksModule,
MessagingModule,
PerformanceModule,
StorageModule,
UtilsModule,
} from '../../types'; } from '../../types';
const FirebaseCoreModule = NativeModules.RNFirebase; const FirebaseCoreModule = NativeModules.RNFirebase;
@ -45,70 +31,57 @@ const FirebaseCoreModule = NativeModules.RNFirebase;
export default class FirebaseApp { export default class FirebaseApp {
_extendedProps: { [string] : boolean }; _extendedProps: { [string] : boolean };
_initialized: boolean; _initialized: boolean = false;
_name: string; _name: string;
_namespaces: { [string]: FirebaseModule }; _nativeInitialized: boolean = false;
_nativeInitialized: boolean;
_options: FirebaseOptions; _options: FirebaseOptions;
admob: AdMobModule; admob: () => AdMob;
analytics: AnalyticsModule; analytics: () => Analytics;
auth: AuthModule; auth: () => Auth;
config: ConfigModule; config: () => Config;
crash: CrashModule; crash: () => Crash;
database: DatabaseModule; database: () => Database;
fabric: FabricModule; fabric: {
firestore: FirestoreModule; crashlytics: () => Crashlytics,
links: LinksModule; };
messaging: MessagingModule; firestore: () => Firestore;
perf: PerformanceModule; links: () => Links;
storage: StorageModule; messaging: () => Messaging;
utils: UtilsModule; perf: () => Performance;
storage: () => Storage;
utils: () => Utils;
constructor(name: string, options: FirebaseOptions) { constructor(name: string, options: FirebaseOptions, fromNative: boolean = false) {
this._name = name; this._name = name;
this._namespaces = {};
this._options = Object.assign({}, options); this._options = Object.assign({}, options);
// native ios/android to confirm initialized if (fromNative) {
this._initialized = false;
this._nativeInitialized = false;
// modules
this.admob = this._staticsOrModuleInstance(AdMobStatics, AdMob);
this.analytics = this._staticsOrModuleInstance(AnalyticsStatics, Analytics);
this.auth = this._staticsOrModuleInstance(AuthStatics, Auth);
this.config = this._staticsOrModuleInstance(ConfigStatics, Config);
this.crash = this._staticsOrModuleInstance(CrashStatics, Crash);
this.database = this._staticsOrModuleInstance(DatabaseStatics, Database);
this.fabric = {
crashlytics: this._staticsOrModuleInstance(CrashlyticsStatics, Crashlytics),
};
this.firestore = this._staticsOrModuleInstance(FirestoreStatics, Firestore);
this.links = this._staticsOrModuleInstance(LinksStatics, Links);
this.messaging = this._staticsOrModuleInstance(MessagingStatics, Messaging);
this.perf = this._staticsOrModuleInstance(PerformanceStatics, Performance);
this.storage = this._staticsOrModuleInstance(StorageStatics, Storage);
this.utils = this._staticsOrModuleInstance(UtilsStatics, Utils);
this._extendedProps = {};
}
/**
*
* @param native
* @private
*/
_initializeApp(native: boolean = false) {
if (native) {
// for apps already initialized natively that
// we have info from RN constants
this._initialized = true; this._initialized = true;
this._nativeInitialized = true; this._nativeInitialized = true;
} else { } else if (options.databaseURL && options.apiKey) {
FirebaseCoreModule.initializeApp(this._name, this._options, (error, result) => { FirebaseCoreModule.initializeApp(this._name, this._options, (error, result) => {
this._initialized = true; this._initialized = true;
INTERNALS.SharedEventEmitter.emit(`AppReady:${this._name}`, { error, result }); SharedEventEmitter.emit(`AppReady:${this._name}`, { error, result });
}); });
} }
// modules
this.admob = APPS.appModule(this, AdmobNamespace, AdMob);
this.analytics = APPS.appModule(this, AnalyticsNamespace, Analytics);
this.auth = APPS.appModule(this, AuthNamespace, Auth);
this.config = APPS.appModule(this, ConfigNamespace, Config);
this.crash = APPS.appModule(this, CrashNamespace, Crash);
this.database = APPS.appModule(this, DatabaseNamespace, Database);
this.fabric = {
crashlytics: APPS.appModule(this, CrashlyticsNamespace, Crashlytics),
};
this.firestore = APPS.appModule(this, FirestoreNamespace, Firestore);
this.links = APPS.appModule(this, LinksNamespace, Links);
this.messaging = APPS.appModule(this, MessagingNamespace, Messaging);
this.perf = APPS.appModule(this, PerfNamespace, Performance);
this.storage = APPS.appModule(this, StorageNamespace, Storage);
this.utils = APPS.appModule(this, UtilsNamespace, Utils);
this._extendedProps = {};
} }
/** /**
@ -116,13 +89,6 @@ export default class FirebaseApp {
* @return {*} * @return {*}
*/ */
get name(): string { get name(): string {
if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME) {
// ios and android firebase sdk's return different
// app names - so we just return what the web sdk
// would if it was default.
return '[DEFAULT]';
}
return this._name; return this._name;
} }
@ -165,7 +131,7 @@ export default class FirebaseApp {
delete() { delete() {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('app', 'delete')); throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('app', 'delete'));
// TODO only the ios sdk currently supports delete, add back in when android also supports it // TODO only the ios sdk currently supports delete, add back in when android also supports it
// if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME && this._nativeInitialized) { // if (this._name === APPS.DEFAULT_APP_NAME && this._nativeInitialized) {
// return Promise.reject( // return Promise.reject(
// new Error('Unable to delete the default native firebase app instance.'), // new Error('Unable to delete the default native firebase app instance.'),
// ); // );
@ -183,38 +149,10 @@ export default class FirebaseApp {
if (this._initialized) return Promise.resolve(this); if (this._initialized) return Promise.resolve(this);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
INTERNALS.SharedEventEmitter.once(`AppReady:${this._name}`, ({ error }) => { SharedEventEmitter.once(`AppReady:${this._name}`, ({ error }) => {
if (error) return reject(new Error(error)); // error is a string as it's from native if (error) return reject(new Error(error)); // error is a string as it's from native
return resolve(this); // return app return resolve(this); // return app
}); });
}); });
} }
/**
*
* @param statics
* @param InstanceClass
* @return {function()}
* @private
*/
_staticsOrModuleInstance<M: FirebaseModule, S:FirebaseStatics>(statics: S, InstanceClass: Class<M>): FirebaseModuleAndStatics<M, S> {
const getInstance = (): M => {
const _name = `_${InstanceClass._NAMESPACE}`;
if (isAndroid && InstanceClass._NAMESPACE !== Utils._NAMESPACE && !INTERNALS.FLAGS.checkedPlayServices) {
INTERNALS.FLAGS.checkedPlayServices = true;
this.utils().checkPlayServicesAvailability();
}
if (!this._namespaces[_name]) {
this._namespaces[_name] = new InstanceClass(this, this._options);
}
return this._namespaces[_name];
};
return Object.assign(getInstance, statics, {
nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE],
});
}
} }

View File

@ -2,26 +2,26 @@
* @providesModule Firebase * @providesModule Firebase
* @flow * @flow
*/ */
import { NativeModules, NativeEventEmitter } from 'react-native'; import { NativeModules } from 'react-native';
import APPS from '../../utils/apps';
import INTERNALS from '../../utils/internals'; import INTERNALS from '../../utils/internals';
import FirebaseApp from './firebase-app'; import FirebaseApp from './firebase-app';
import { isObject, isString } from '../../utils';
// module imports // module imports
import AdMob, { statics as AdMobStatics } from '../admob'; import { statics as AdMobStatics, MODULE_NAME as AdmobModuleName } from '../admob';
import Auth, { statics as AuthStatics } from '../auth'; import { statics as AuthStatics, MODULE_NAME as AuthModuleName } from '../auth';
import Analytics, { statics as AnalyticsStatics } from '../analytics'; import { statics as AnalyticsStatics, MODULE_NAME as AnalyticsModuleName } from '../analytics';
import Config, { statics as ConfigStatics } from '../config'; import { statics as ConfigStatics, MODULE_NAME as ConfigModuleName } from '../config';
import Crash, { statics as CrashStatics } from '../crash'; import { statics as CrashStatics, MODULE_NAME as CrashModuleName } from '../crash';
import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics'; import { statics as CrashlyticsStatics, MODULE_NAME as CrashlyticsModuleName } from '../fabric/crashlytics';
import Database, { statics as DatabaseStatics } from '../database'; import { statics as DatabaseStatics, MODULE_NAME as DatabaseModuleName } from '../database';
import Firestore, { statics as FirestoreStatics } from '../firestore'; import { statics as FirestoreStatics, MODULE_NAME as FirestoreModuleName } from '../firestore';
import Links, { statics as LinksStatics } from '../links'; import { statics as LinksStatics, MODULE_NAME as LinksModuleName } from '../links';
import Messaging, { statics as MessagingStatics } from '../messaging'; import { statics as MessagingStatics, MODULE_NAME as MessagingModuleName } from '../messaging';
import Performance, { statics as PerformanceStatics } from '../perf'; import { statics as PerformanceStatics, MODULE_NAME as PerfModuleName } from '../perf';
import Storage, { statics as StorageStatics } from '../storage'; import { statics as StorageStatics, MODULE_NAME as StorageModuleName } from '../storage';
import Utils, { statics as UtilsStatics } from '../utils'; import { statics as UtilsStatics, MODULE_NAME as UtilsModuleName } from '../utils';
import type { import type {
AdMobModule, AdMobModule,
@ -31,10 +31,7 @@ import type {
CrashModule, CrashModule,
DatabaseModule, DatabaseModule,
FabricModule, FabricModule,
FirebaseModule,
FirebaseModuleAndStatics,
FirebaseOptions, FirebaseOptions,
FirebaseStatics,
FirestoreModule, FirestoreModule,
LinksModule, LinksModule,
MessagingModule, MessagingModule,
@ -46,8 +43,6 @@ import type {
const FirebaseCoreModule = NativeModules.RNFirebase; const FirebaseCoreModule = NativeModules.RNFirebase;
class FirebaseCore { class FirebaseCore {
_nativeEmitters: { [string]: NativeEventEmitter };
_nativeSubscriptions: { [string]: boolean };
admob: AdMobModule; admob: AdMobModule;
analytics: AnalyticsModule; analytics: AnalyticsModule;
auth: AuthModule; auth: AuthModule;
@ -63,45 +58,27 @@ class FirebaseCore {
utils: UtilsModule; utils: UtilsModule;
constructor() { constructor() {
this._nativeEmitters = {};
this._nativeSubscriptions = {};
if (!FirebaseCoreModule) { if (!FirebaseCoreModule) {
throw (new Error(INTERNALS.STRINGS.ERROR_MISSING_CORE)); throw (new Error(INTERNALS.STRINGS.ERROR_MISSING_CORE));
} }
APPS.initializeNativeApps();
this._initializeNativeApps();
// modules // modules
this.admob = this._appNamespaceOrStatics(AdMobStatics, AdMob); this.admob = APPS.moduleAndStatics('admob', AdMobStatics, AdmobModuleName);
this.analytics = this._appNamespaceOrStatics(AnalyticsStatics, Analytics); this.analytics = APPS.moduleAndStatics('analytics', AnalyticsStatics, AnalyticsModuleName);
this.auth = this._appNamespaceOrStatics(AuthStatics, Auth); this.auth = APPS.moduleAndStatics('auth', AuthStatics, AuthModuleName);
this.config = this._appNamespaceOrStatics(ConfigStatics, Config); this.config = APPS.moduleAndStatics('config', ConfigStatics, ConfigModuleName);
this.crash = this._appNamespaceOrStatics(CrashStatics, Crash); this.crash = APPS.moduleAndStatics('crash', CrashStatics, CrashModuleName);
this.database = this._appNamespaceOrStatics(DatabaseStatics, Database); this.database = APPS.moduleAndStatics('database', DatabaseStatics, DatabaseModuleName);
this.fabric = { this.fabric = {
crashlytics: this._appNamespaceOrStatics(CrashlyticsStatics, Crashlytics), crashlytics: APPS.moduleAndStatics('crashlytics', CrashlyticsStatics, CrashlyticsModuleName),
}; };
this.firestore = this._appNamespaceOrStatics(FirestoreStatics, Firestore); this.firestore = APPS.moduleAndStatics('firestore', FirestoreStatics, FirestoreModuleName);
this.links = this._appNamespaceOrStatics(LinksStatics, Links); this.links = APPS.moduleAndStatics('links', LinksStatics, LinksModuleName);
this.messaging = this._appNamespaceOrStatics(MessagingStatics, Messaging); this.messaging = APPS.moduleAndStatics('messaging', MessagingStatics, MessagingModuleName);
this.perf = this._appNamespaceOrStatics(PerformanceStatics, Performance); this.perf = APPS.moduleAndStatics('perf', PerformanceStatics, PerfModuleName);
this.storage = this._appNamespaceOrStatics(StorageStatics, Storage); this.storage = APPS.moduleAndStatics('storage', StorageStatics, StorageModuleName);
this.utils = this._appNamespaceOrStatics(UtilsStatics, Utils); this.utils = APPS.moduleAndStatics('utils', UtilsStatics, UtilsModuleName);
}
/**
* Bootstraps all native app instances that were discovered on boot
* @private
*/
_initializeNativeApps() {
for (let i = 0, len = FirebaseCoreModule.apps.length; i < len; i++) {
const app = FirebaseCoreModule.apps[i];
const options = Object.assign({}, app);
delete options.name;
INTERNALS.APPS[app.name] = new FirebaseApp(app.name, options);
INTERNALS.APPS[app.name]._initializeApp(true);
}
} }
/** /**
@ -112,57 +89,7 @@ class FirebaseCore {
* @return {*} * @return {*}
*/ */
initializeApp(options: FirebaseOptions, name: string): FirebaseApp { initializeApp(options: FirebaseOptions, name: string): FirebaseApp {
if (name && !isString(name)) { return APPS.initializeApp(options, name);
throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME);
}
const _name = (name || INTERNALS.STRINGS.DEFAULT_APP_NAME).toUpperCase();
// return an existing app if found
// todo in v4 remove deprecation and throw an error
if (INTERNALS.APPS[_name]) {
console.warn(INTERNALS.STRINGS.WARN_INITIALIZE_DEPRECATION);
return INTERNALS.APPS[_name];
}
// only validate if app doesn't already exist
// to allow apps already initialized natively
// to still go through init without erroring (backwards compatibility)
if (!isObject(options)) {
throw new Error(INTERNALS.STRINGS.ERROR_INIT_OBJECT);
}
if (!options.apiKey) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('apiKey'));
}
if (!options.appId) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('appId'));
}
if (!options.databaseURL) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('databaseURL'));
}
if (!options.messagingSenderId) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('messagingSenderId'));
}
if (!options.projectId) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('projectId'));
}
if (!options.storageBucket) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('storageBucket'));
}
INTERNALS.APPS[_name] = new FirebaseApp(_name, options);
// only initialize if certain props are available
if (options.databaseURL && options.apiKey) {
INTERNALS.APPS[_name]._initializeApp();
}
return INTERNALS.APPS[_name];
} }
/** /**
@ -175,10 +102,7 @@ class FirebaseCore {
* @return {*} * @return {*}
*/ */
app(name?: string): FirebaseApp { app(name?: string): FirebaseApp {
const _name = name ? name.toUpperCase() : INTERNALS.STRINGS.DEFAULT_APP_NAME; return APPS.app(name);
const app = INTERNALS.APPS[_name];
if (!app) throw new Error(INTERNALS.STRINGS.ERROR_APP_NOT_INIT(_name));
return app;
} }
/** /**
@ -186,83 +110,7 @@ class FirebaseCore {
* @return {Array} * @return {Array}
*/ */
get apps(): Array<FirebaseApp> { get apps(): Array<FirebaseApp> {
return Object.values(INTERNALS.APPS); return APPS.apps();
}
/*
* INTERNALS
*/
/**
* Subscribe to a native event for js side distribution by appName
* React Native events are hard set at compile - cant do dynamic event names
* so we use a single event send it to js and js then internally can prefix it
* and distribute dynamically.
*
* @param eventName
* @param nativeEmitter
* @private
*/
_subscribeForDistribution(eventName: string, nativeEmitter: NativeEventEmitter) {
if (!this._nativeSubscriptions[eventName]) {
nativeEmitter.addListener(eventName, (event) => {
if (event.appName) {
// native event has an appName property - auto prefix and internally emit
INTERNALS.SharedEventEmitter.emit(`${event.appName}-${eventName}`, event);
} else {
// standard event - no need to prefix
INTERNALS.SharedEventEmitter.emit(eventName, event);
}
});
this._nativeSubscriptions[eventName] = true;
}
}
/**
*
* @param statics
* @param InstanceClass
* @return {function(FirebaseApp=)}
* @private
*/
_appNamespaceOrStatics<M: FirebaseModule, S: FirebaseStatics>(statics: S, InstanceClass: Class<M>): FirebaseModuleAndStatics<M, S> {
const namespace = InstanceClass._NAMESPACE;
const getNamespace = (app?: FirebaseApp) => {
let _app = app;
// throw an error if it's not a valid app instance
if (_app && !(_app instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace));
// default to the 'DEFAULT' app if no arg provided - will throw an error
// if default app not initialized
else if (!_app) _app = this.app(INTERNALS.STRINGS.DEFAULT_APP_NAME);
const firebaseApp = INTERNALS.APPS[_app._name];
if (namespace === 'crashlytics') {
return firebaseApp.fabric[namespace](_app);
}
return firebaseApp[namespace](_app);
};
return Object.assign(getNamespace, statics, {
nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE],
});
}
/**
*
* @param name
* @param nativeModule
* @return {*}
* @private
*/
_getOrSetNativeEmitter(name: string, nativeModule: Object): NativeEventEmitter {
if (this._nativeEmitters[name]) {
return this._nativeEmitters[name];
}
return this._nativeEmitters[name] = new NativeEventEmitter(nativeModule);
} }
} }

View File

@ -7,12 +7,15 @@ import ModuleBase from '../../utils/ModuleBase';
import type FirebaseApp from '../core/firebase-app'; import type FirebaseApp from '../core/firebase-app';
import type { FirebaseError } from '../../types'; import type { FirebaseError } from '../../types';
export default class Crash extends ModuleBase { export const MODULE_NAME = 'RNFirebaseCrash';
static _NAMESPACE = 'crash'; export const NAMESPACE = 'crash';
static _NATIVE_MODULE = 'RNFirebaseCrash';
export default class Crash extends ModuleBase {
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options); super(firebaseApp, options, {
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
} }
/** /**

View File

@ -10,19 +10,31 @@ import ModuleBase from './../../utils/ModuleBase';
import type FirebaseApp from '../core/firebase-app'; import type FirebaseApp from '../core/firebase-app';
const NATIVE_EVENTS = [
'database_transaction_event',
// 'database_server_offset', // TODO
];
export const MODULE_NAME = 'RNFirebaseDatabase';
export const NAMESPACE = 'database';
/** /**
* @class Database * @class Database
*/ */
export default class Database extends ModuleBase { export default class Database extends ModuleBase {
static _NAMESPACE = 'database';
static _NATIVE_MODULE = 'RNFirebaseDatabase';
_offsetRef: Reference; _offsetRef: Reference;
_serverTimeOffset: number; _serverTimeOffset: number;
_transactionHandler: TransactionHandler; _transactionHandler: TransactionHandler;
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options, true); super(firebaseApp, {
persistence: false,
...options,
}, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
this._transactionHandler = new TransactionHandler(this); this._transactionHandler = new TransactionHandler(this);
if (this._options.persistence) { if (this._options.persistence) {
@ -79,8 +91,8 @@ export const statics = {
TIMESTAMP: NativeModules.RNFirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' }, TIMESTAMP: NativeModules.RNFirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' },
} : {}, } : {},
enableLogging(enabled: boolean) { enableLogging(enabled: boolean) {
if (NativeModules[Database._NATIVE_MODULE]) { if (NativeModules[MODULE_NAME]) {
NativeModules[Database._NATIVE_MODULE].enableLogging(enabled); NativeModules[MODULE_NAME].enableLogging(enabled);
} }
}, },
}; };

View File

@ -5,6 +5,7 @@
import Query from './query.js'; import Query from './query.js';
import Snapshot from './snapshot'; import Snapshot from './snapshot';
import Disconnect from './disconnect'; import Disconnect from './disconnect';
import { getLogger } from '../../utils/log';
import ReferenceBase from '../../utils/ReferenceBase'; import ReferenceBase from '../../utils/ReferenceBase';
import { import {
@ -17,10 +18,10 @@ import {
generatePushID, generatePushID,
} from '../../utils'; } from '../../utils';
import INTERNALS from '../../utils/internals'; import SyncTree from '../../utils/SyncTree';
import type Database from './';
import type { DatabaseModifier, FirebaseError } from '../../types'; import type { DatabaseModifier, FirebaseError } from '../../types';
import type SyncTree from '../../utils/SyncTree';
// track all event registrations by path // track all event registrations by path
let listeners = 0; let listeners = 0;
@ -73,18 +74,18 @@ type DatabaseListener = {
* @extends ReferenceBase * @extends ReferenceBase
*/ */
export default class Reference extends ReferenceBase { export default class Reference extends ReferenceBase {
_database: Object; _database: Database;
_promise: ?Promise<*>; _promise: ?Promise<*>;
_query: Query; _query: Query;
_refListeners: { [listenerId: number]: DatabaseListener }; _refListeners: { [listenerId: number]: DatabaseListener };
constructor(database: Object, path: string, existingModifiers?: Array<DatabaseModifier>) { constructor(database: Database, path: string, existingModifiers?: Array<DatabaseModifier>) {
super(path, database); super(path, database);
this._promise = null; this._promise = null;
this._refListeners = {}; this._refListeners = {};
this._database = database; this._database = database;
this._query = new Query(this, path, existingModifiers); this._query = new Query(this, path, existingModifiers);
this.log.debug('Created new Reference', this._getRefKey()); getLogger(database).debug('Created new Reference', this._getRefKey());
} }
/** /**
@ -535,7 +536,7 @@ export default class Reference extends ReferenceBase {
* @return {string} * @return {string}
*/ */
_getRegistrationKey(eventType: string): string { _getRegistrationKey(eventType: string): string {
return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}$${listeners}$${eventType}`; return `$${this._database.app.name}$/${this.path}$${this._query.queryIdentifier()}$${listeners}$${eventType}`;
} }
/** /**
@ -546,14 +547,7 @@ export default class Reference extends ReferenceBase {
* @private * @private
*/ */
_getRefKey(): string { _getRefKey(): string {
return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}`; return `$${this._database.app.name}$/${this.path}$${this._query.queryIdentifier()}`;
}
/**
* Return instance of db logger
*/
get log() {
return this._database.log;
} }
/** /**
@ -659,23 +653,23 @@ export default class Reference extends ReferenceBase {
ref: this, ref: this,
path: this.path, path: this.path,
key: this._getRefKey(), key: this._getRefKey(),
appName: this._database._appName, appName: this._database.app.name,
eventRegistrationKey, eventRegistrationKey,
}; };
this._syncTree.addRegistration(registrationObj, _context ? callback.bind(_context) : callback); SyncTree.addRegistration(registrationObj, _context ? callback.bind(_context) : callback);
if (isFunction(cancelCallbackOrContext)) { if (isFunction(cancelCallbackOrContext)) {
// cancellations have their own separate registration // cancellations have their own separate registration
// as these are one off events, and they're not guaranteed // as these are one off events, and they're not guaranteed
// to occur either, only happens on failure to register on native // to occur either, only happens on failure to register on native
this._syncTree.addRegistration( SyncTree.addRegistration(
{ {
ref: this, ref: this,
once: true, once: true,
path: this.path, path: this.path,
key: this._getRefKey(), key: this._getRefKey(),
appName: this._database._appName, appName: this._database.app.name,
eventType: `${eventType}$cancelled`, eventType: `${eventType}$cancelled`,
eventRegistrationKey: registrationCancellationKey, eventRegistrationKey: registrationCancellationKey,
}, },
@ -688,7 +682,7 @@ export default class Reference extends ReferenceBase {
eventType, eventType,
path: this.path, path: this.path,
key: this._getRefKey(), key: this._getRefKey(),
appName: this._database._appName, appName: this._database.app.name,
modifiers: this._query.getModifiers(), modifiers: this._query.getModifiers(),
hasCancellationCallback: isFunction(cancelCallbackOrContext), hasCancellationCallback: isFunction(cancelCallbackOrContext),
registration: { registration: {
@ -726,7 +720,7 @@ export default class Reference extends ReferenceBase {
if (!arguments.length) { if (!arguments.length) {
// Firebase Docs: // Firebase Docs:
// if no eventType or callback is specified, all callbacks for the Reference will be removed. // if no eventType or callback is specified, all callbacks for the Reference will be removed.
return this._syncTree.removeListenersForRegistrations(this._syncTree.getRegistrationsByPath(this.path)); return SyncTree.removeListenersForRegistrations(SyncTree.getRegistrationsByPath(this.path));
} }
/* /*
@ -747,29 +741,25 @@ export default class Reference extends ReferenceBase {
// remove the callback. // remove the callback.
// Remove only a single registration // Remove only a single registration
if (eventType && originalCallback) { if (eventType && originalCallback) {
const registration = this._syncTree.getOneByPathEventListener(this.path, eventType, originalCallback); const registration = SyncTree.getOneByPathEventListener(this.path, eventType, originalCallback);
if (!registration) return []; if (!registration) return [];
// remove the paired cancellation registration if any exist // remove the paired cancellation registration if any exist
this._syncTree.removeListenersForRegistrations([`${registration}$cancelled`]); SyncTree.removeListenersForRegistrations([`${registration}$cancelled`]);
// remove only the first registration to match firebase web sdk // remove only the first registration to match firebase web sdk
// call multiple times to remove multiple registrations // call multiple times to remove multiple registrations
return this._syncTree.removeListenerRegistrations(originalCallback, [registration]); return SyncTree.removeListenerRegistrations(originalCallback, [registration]);
} }
// Firebase Docs: // Firebase Docs:
// If a callback is not specified, all callbacks for the specified eventType will be removed. // If a callback is not specified, all callbacks for the specified eventType will be removed.
const registrations = this._syncTree.getRegistrationsByPathEvent(this.path, eventType); const registrations = SyncTree.getRegistrationsByPathEvent(this.path, eventType);
this._syncTree.removeListenersForRegistrations( SyncTree.removeListenersForRegistrations(
this._syncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`), SyncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`),
); );
return this._syncTree.removeListenersForRegistrations(registrations); return SyncTree.removeListenersForRegistrations(registrations);
}
get _syncTree(): SyncTree {
return INTERNALS.SyncTree;
} }
} }

View File

@ -2,6 +2,8 @@
* @flow * @flow
* Database Transaction representation wrapper * Database Transaction representation wrapper
*/ */
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
import { getLogger } from '../../utils/log';
import type Database from './'; import type Database from './';
let transactionId = 0; let transactionId = 0;
@ -18,8 +20,8 @@ export default class TransactionHandler {
this._transactions = {}; this._transactions = {};
this._database = database; this._database = database;
this._transactionListener = this._database.addListener( this._transactionListener = SharedEventEmitter.addListener(
this._database._getAppEventName('database_transaction_event'), getAppEventName(this._database, 'database_transaction_event'),
this._handleTransactionEvent.bind(this), this._handleTransactionEvent.bind(this),
); );
} }
@ -75,7 +77,7 @@ export default class TransactionHandler {
case 'complete': case 'complete':
return this._handleComplete(event); return this._handleComplete(event);
default: default:
this.log.warn(`Unknown transaction event type: '${event.type}'`, event); getLogger(this._database).warn(`Unknown transaction event type: '${event.type}'`, event);
return undefined; return undefined;
} }
} }

View File

@ -6,12 +6,15 @@ import ModuleBase from '../../../utils/ModuleBase';
import type FirebaseApp from '../../core/firebase-app'; import type FirebaseApp from '../../core/firebase-app';
export default class Crashlytics extends ModuleBase { export const MODULE_NAME = 'RNFirebaseCrashlytics';
static _NAMESPACE = 'crashlytics'; export const NAMESPACE = 'crashlytics';
static _NATIVE_MODULE = 'RNFirebaseCrashlytics';
export default class Crashlytics extends ModuleBase {
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options); super(firebaseApp, options, {
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
} }
/** /**

View File

@ -5,6 +5,8 @@
import CollectionReference from './CollectionReference'; import CollectionReference from './CollectionReference';
import DocumentSnapshot from './DocumentSnapshot'; import DocumentSnapshot from './DocumentSnapshot';
import { buildNativeMap } from './utils/serialize'; import { buildNativeMap } from './utils/serialize';
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
import { getLogger } from '../../utils/log';
import { firestoreAutoId, isFunction, isObject, isString } from '../../utils'; import { firestoreAutoId, isFunction, isObject, isString } from '../../utils';
import type Firestore from './'; import type Firestore from './';
@ -136,15 +138,15 @@ export default class DocumentReference {
}; };
// Listen to snapshot events // Listen to snapshot events
this._firestore.on( SharedEventEmitter.addListener(
this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`),
listener, listener,
); );
// Listen for snapshot error events // Listen for snapshot error events
if (observer.error) { if (observer.error) {
this._firestore.on( SharedEventEmitter.addListener(
this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`), getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`),
observer.error, observer.error,
); );
} }
@ -196,9 +198,9 @@ export default class DocumentReference {
* @param listener * @param listener
*/ */
_offDocumentSnapshot(listenerId: string, listener: Function) { _offDocumentSnapshot(listenerId: string, listener: Function) {
this._firestore.log.info('Removing onDocumentSnapshot listener'); getLogger(this._firestore).info('Removing onDocumentSnapshot listener');
this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener);
this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), listener);
this._firestore._native this._firestore._native
.documentOffSnapshot(this.path, listenerId); .documentOffSnapshot(this.path, listenerId);
} }

View File

@ -5,6 +5,8 @@
import DocumentSnapshot from './DocumentSnapshot'; import DocumentSnapshot from './DocumentSnapshot';
import QuerySnapshot from './QuerySnapshot'; import QuerySnapshot from './QuerySnapshot';
import { buildNativeArray, buildTypeMap } from './utils/serialize'; import { buildNativeArray, buildTypeMap } from './utils/serialize';
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
import { getLogger } from '../../utils/log';
import { firestoreAutoId, isFunction, isObject } from '../../utils'; import { firestoreAutoId, isFunction, isObject } from '../../utils';
import type Firestore from './'; import type Firestore from './';
@ -206,15 +208,15 @@ export default class Query {
}; };
// Listen to snapshot events // Listen to snapshot events
this._firestore.on( SharedEventEmitter.addListener(
this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`), getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`),
listener, listener,
); );
// Listen for snapshot error events // Listen for snapshot error events
if (observer.error) { if (observer.error) {
this._firestore.on( SharedEventEmitter.addListener(
this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`), getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`),
observer.error, observer.error,
); );
} }
@ -334,9 +336,9 @@ export default class Query {
* @param listener * @param listener
*/ */
_offCollectionSnapshot(listenerId: string, listener: Function) { _offCollectionSnapshot(listenerId: string, listener: Function) {
this._firestore.log.info('Removing onQuerySnapshot listener'); getLogger(this._firestore).info('Removing onQuerySnapshot listener');
this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`), listener);
this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`), listener);
this._firestore._native this._firestore._native
.collectionOffSnapshot( .collectionOffSnapshot(
this._referencePath.relativeName, this._referencePath.relativeName,

View File

@ -4,7 +4,8 @@
*/ */
import { NativeModules } from 'react-native'; import { NativeModules } from 'react-native';
import ModuleBase from './../../utils/ModuleBase'; import { getAppEventName, SharedEventEmitter } from '../../utils/events';
import ModuleBase from '../../utils/ModuleBase';
import CollectionReference from './CollectionReference'; import CollectionReference from './CollectionReference';
import DocumentReference from './DocumentReference'; import DocumentReference from './DocumentReference';
import FieldValue from './FieldValue'; import FieldValue from './FieldValue';
@ -33,64 +34,41 @@ type DocumentSyncEvent = {
path: string, path: string,
} }
class FirestoreInternalModule extends ModuleBase { const NATIVE_EVENTS = [
static _NAMESPACE = 'firestore'; 'firestore_collection_sync_event',
static _NATIVE_MODULE = 'RNFirebaseFirestore'; 'firestore_document_sync_event',
];
_referencePath: Path; export const MODULE_NAME = 'RNFirebaseFirestore';
export const NAMESPACE = 'firestore';
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options, true);
this._referencePath = new Path([]);
super.addListener(
// sub to internal native event - this fans out to
// public event name: onCollectionSnapshot
super._getAppEventName('firestore_collection_sync_event'),
this._onCollectionSyncEvent.bind(this),
);
super.addListener(
// sub to internal native event - this fans out to
// public event name: onDocumentSnapshot
super._getAppEventName('firestore_document_sync_event'),
this._onDocumentSyncEvent.bind(this),
);
}
/**
* Internal collection sync listener
* @param event
* @private
*/
_onCollectionSyncEvent(event: CollectionSyncEvent) {
if (event.error) {
this.emit(super._getAppEventName(`onQuerySnapshotError:${event.listenerId}`), event.error);
} else {
this.emit(super._getAppEventName(`onQuerySnapshot:${event.listenerId}`), event.querySnapshot);
}
}
/**
* Internal document sync listener
* @param event
* @private
*/
_onDocumentSyncEvent(event: DocumentSyncEvent) {
if (event.error) {
this.emit(super._getAppEventName(`onDocumentSnapshotError:${event.listenerId}`), event.error);
} else {
this.emit(super._getAppEventName(`onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot);
}
}
}
/** /**
* @class Firestore * @class Firestore
*/ */
export default class Firestore extends FirestoreInternalModule { export default class Firestore extends ModuleBase {
_referencePath: Path;
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options); super(firebaseApp, options, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
this._referencePath = new Path([]);
SharedEventEmitter.addListener(
// sub to internal native event - this fans out to
// public event name: onCollectionSnapshot
getAppEventName(this, 'firestore_collection_sync_event'),
this._onCollectionSyncEvent.bind(this),
);
SharedEventEmitter.addListener(
// sub to internal native event - this fans out to
// public event name: onDocumentSnapshot
getAppEventName(this, 'firestore_document_sync_event'),
this._onDocumentSyncEvent.bind(this),
);
} }
batch(): WriteBatch { batch(): WriteBatch {
@ -134,20 +112,46 @@ export default class Firestore extends FirestoreInternalModule {
} }
setLogLevel(): void { setLogLevel(): void {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Firestore, 'setLogLevel')); throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('firestore', 'setLogLevel'));
} }
settings(): void { settings(): void {
throw new Error('firebase.firestore().settings() coming soon'); throw new Error('firebase.firestore().settings() coming soon');
} }
/**
* Internal collection sync listener
* @param event
* @private
*/
_onCollectionSyncEvent(event: CollectionSyncEvent) {
if (event.error) {
SharedEventEmitter.emit(getAppEventName(this, `onQuerySnapshotError:${event.listenerId}`), event.error);
} else {
SharedEventEmitter.emit(getAppEventName(this, `onQuerySnapshot:${event.listenerId}`), event.querySnapshot);
}
}
/**
* Internal document sync listener
* @param event
* @private
*/
_onDocumentSyncEvent(event: DocumentSyncEvent) {
if (event.error) {
SharedEventEmitter.emit(getAppEventName(this, `onDocumentSnapshotError:${event.listenerId}`), event.error);
} else {
SharedEventEmitter.emit(getAppEventName(this, `onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot);
}
}
} }
export const statics = { export const statics = {
FieldValue, FieldValue,
GeoPoint, GeoPoint,
enableLogging(bool) { enableLogging(enabled: boolean) {
if (NativeModules[Firestore._NATIVE_MODULE]) { if (NativeModules[MODULE_NAME]) {
NativeModules[Firestore._NATIVE_MODULE].enableLogging(bool); NativeModules[MODULE_NAME].enableLogging(enabled);
} }
}, },
}; };

View File

@ -2,7 +2,8 @@
* @flow * @flow
* Dynamic Links representation wrapper * Dynamic Links representation wrapper
*/ */
import ModuleBase from './../../utils/ModuleBase'; import { SharedEventEmitter } from '../../utils/events';
import ModuleBase from '../../utils/ModuleBase';
import { areObjectKeysContainedInOther, isObject, isString } from './../../utils'; import { areObjectKeysContainedInOther, isObject, isString } from './../../utils';
import type FirebaseApp from '../core/firebase-app'; import type FirebaseApp from '../core/firebase-app';
@ -11,6 +12,13 @@ const EVENT_TYPE = {
Link: 'dynamic_link_received', Link: 'dynamic_link_received',
}; };
const NATIVE_EVENTS = [
EVENT_TYPE.Link,
];
export const MODULE_NAME = 'RNFirebaseLinks';
export const NAMESPACE = 'links';
function validateParameters(parameters: Object): void { function validateParameters(parameters: Object): void {
const suportedParametersObject = { const suportedParametersObject = {
dynamicLinkDomain: 'string', dynamicLinkDomain: 'string',
@ -62,11 +70,12 @@ function checkForMandatoryParameters(parameters: Object): void {
* @class Links * @class Links
*/ */
export default class Links extends ModuleBase { export default class Links extends ModuleBase {
static _NAMESPACE = 'links';
static _NATIVE_MODULE = 'RNFirebaseLinks';
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options, true); super(firebaseApp, options, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
} }
get EVENT_TYPE(): Object { get EVENT_TYPE(): Object {
@ -87,7 +96,7 @@ export default class Links extends ModuleBase {
* @returns {Function} * @returns {Function}
*/ */
onLink(listener: Function): () => any { onLink(listener: Function): () => any {
const rnListener = this._eventEmitter.addListener(EVENT_TYPE.Link, listener); const rnListener = SharedEventEmitter.addListener(EVENT_TYPE.Link, listener);
return () => rnListener.remove(); return () => rnListener.remove();
} }

View File

@ -3,7 +3,8 @@
* Messaging representation wrapper * Messaging representation wrapper
*/ */
import { Platform, NativeModules } from 'react-native'; import { Platform, NativeModules } from 'react-native';
import ModuleBase from './../../utils/ModuleBase'; import { SharedEventEmitter } from '../../utils/events';
import ModuleBase from '../../utils/ModuleBase';
import RemoteMessage from './RemoteMessage'; import RemoteMessage from './RemoteMessage';
import type FirebaseApp from '../core/firebase-app'; import type FirebaseApp from '../core/firebase-app';
@ -31,6 +32,11 @@ const WILL_PRESENT_RESULT = {
None: 'UNNotificationPresentationOptionNone', None: 'UNNotificationPresentationOptionNone',
}; };
const NATIVE_EVENTS = [
EVENT_TYPE.RefreshToken,
EVENT_TYPE.Notification,
];
const FirebaseMessaging = NativeModules.RNFirebaseMessaging; const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
/** /**
@ -73,16 +79,19 @@ function finish(data) {
} }
} }
export const MODULE_NAME = 'RNFirebaseMessaging';
export const NAMESPACE = 'messaging';
/** /**
* @class Messaging * @class Messaging
*/ */
export default class Messaging extends ModuleBase { export default class Messaging extends ModuleBase {
static _NAMESPACE = 'messaging';
static _NATIVE_MODULE = 'RNFirebaseMessaging';
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options, true); super(firebaseApp, options, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
} }
get EVENT_TYPE(): Object { get EVENT_TYPE(): Object {
@ -213,7 +222,7 @@ export default class Messaging extends ModuleBase {
* @returns {*} * @returns {*}
*/ */
onMessage(listener: (Object) => any): () => any { onMessage(listener: (Object) => any): () => any {
const rnListener = this._eventEmitter.addListener( const rnListener = SharedEventEmitter.addListener(
EVENT_TYPE.Notification, EVENT_TYPE.Notification,
async (event) => { async (event) => {
const data = { const data = {
@ -236,7 +245,7 @@ export default class Messaging extends ModuleBase {
* @returns {*} * @returns {*}
*/ */
onTokenRefresh(listener: (string) => any): () => any { onTokenRefresh(listener: (string) => any): () => any {
const rnListener = this._eventEmitter.addListener(EVENT_TYPE.RefreshToken, listener); const rnListener = SharedEventEmitter.addListener(EVENT_TYPE.RefreshToken, listener);
return () => rnListener.remove(); return () => rnListener.remove();
} }

View File

@ -7,12 +7,15 @@ import ModuleBase from '../../utils/ModuleBase';
import type FirebaseApp from '../core/firebase-app'; import type FirebaseApp from '../core/firebase-app';
export default class PerformanceMonitoring extends ModuleBase { export const MODULE_NAME = 'RNFirebasePerformance';
static _NAMESPACE = 'perf'; export const NAMESPACE = 'perf';
static _NATIVE_MODULE = 'RNFirebasePerformance';
export default class PerformanceMonitoring extends ModuleBase {
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options); super(firebaseApp, options, {
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
} }
/** /**

View File

@ -5,31 +5,42 @@
import { NativeModules } from 'react-native'; import { NativeModules } from 'react-native';
import StorageRef from './reference'; import StorageRef from './reference';
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
import { getLogger } from '../../utils/log';
import ModuleBase from './../../utils/ModuleBase'; import ModuleBase from './../../utils/ModuleBase';
import type FirebaseApp from '../core/firebase-app'; import type FirebaseApp from '../core/firebase-app';
const FirebaseStorage = NativeModules.RNFirebaseStorage; const FirebaseStorage = NativeModules.RNFirebaseStorage;
export default class Storage extends ModuleBase { const NATIVE_EVENTS = [
static _NAMESPACE = 'storage'; 'storage_event',
static _NATIVE_MODULE = 'RNFirebaseStorage'; 'storage_error',
];
export const MODULE_NAME = 'RNFirebaseStorage';
export const NAMESPACE = 'storage';
export default class Storage extends ModuleBase {
/** /**
* *
* @param firebaseApp * @param firebaseApp
* @param options * @param options
*/ */
constructor(firebaseApp: FirebaseApp, options: Object = {}) { constructor(firebaseApp: FirebaseApp, options: Object = {}) {
super(firebaseApp, options, true); super(firebaseApp, options, {
events: NATIVE_EVENTS,
moduleName: MODULE_NAME,
namespace: NAMESPACE,
});
this.addListener( SharedEventEmitter.addListener(
this._getAppEventName('storage_event'), getAppEventName(this, 'storage_event'),
this._handleStorageEvent.bind(this), this._handleStorageEvent.bind(this),
); );
this.addListener( SharedEventEmitter.addListener(
this._getAppEventName('storage_error'), getAppEventName(this, 'storage_error'),
this._handleStorageEvent.bind(this), this._handleStorageEvent.bind(this),
); );
} }
@ -86,31 +97,31 @@ export default class Storage extends ModuleBase {
* INTERNALS * INTERNALS
*/ */
_getSubEventName(path: string, eventName: string) { _getSubEventName(path: string, eventName: string) {
return this._getAppEventName(`${path}-${eventName}`); return getAppEventName(this, `${path}-${eventName}`);
} }
_handleStorageEvent(event: Object) { _handleStorageEvent(event: Object) {
const { path, eventName } = event; const { path, eventName } = event;
const body = event.body || {}; const body = event.body || {};
this.log.debug('_handleStorageEvent: ', path, eventName, body); getLogger(this).debug('_handleStorageEvent: ', path, eventName, body);
this.emit(this._getSubEventName(path, eventName), body); SharedEventEmitter.emit(this._getSubEventName(path, eventName), body);
} }
_handleStorageError(err: Object) { _handleStorageError(err: Object) {
const { path, eventName } = err; const { path, eventName } = err;
const body = err.body || {}; const body = err.body || {};
this.log.debug('_handleStorageError ->', err); getLogger(this).debug('_handleStorageError ->', err);
this.emit(this._getSubEventName(path, eventName), body); SharedEventEmitter.emit(this._getSubEventName(path, eventName), body);
} }
_addListener(path: string, eventName: string, cb: (evt: Object) => Object): void { _addListener(path: string, eventName: string, cb: (evt: Object) => Object): void {
this.on(this._getSubEventName(path, eventName), cb); SharedEventEmitter.addListener(this._getSubEventName(path, eventName), cb);
} }
_removeListener(path: string, eventName: string, origCB: (evt: Object) => Object): void { _removeListener(path: string, eventName: string, origCB: (evt: Object) => Object): void {
this.removeListener(this._getSubEventName(path, eventName), origCB); SharedEventEmitter.removeListener(this._getSubEventName(path, eventName), origCB);
} }
} }

View File

@ -2,7 +2,6 @@
import { NativeModules } from 'react-native'; import { NativeModules } from 'react-native';
// import { version as ReactVersion } from 'react'; // import { version as ReactVersion } from 'react';
// import ReactNativeVersion from 'react-native/Libraries/Core/ReactNativeVersion'; // import ReactNativeVersion from 'react-native/Libraries/Core/ReactNativeVersion';
import INTERNALS from '../../utils/internals'; import INTERNALS from '../../utils/internals';
import { isIOS } from '../../utils'; import { isIOS } from '../../utils';
import ModuleBase from '../../utils/ModuleBase'; import ModuleBase from '../../utils/ModuleBase';
@ -18,18 +17,17 @@ type GoogleApiAvailabilityType = {
error?: string error?: string
} }
export default class RNFirebaseUtils extends ModuleBase { export const MODULE_NAME = 'RNFirebaseUtils';
static _NAMESPACE = 'utils'; export const NAMESPACE = 'utils';
static _NATIVE_DISABLED = true;
static _NATIVE_MODULE = 'RNFirebaseUtils';
export default class RNFirebaseUtils extends ModuleBase {
/** /**
* *
*/ */
checkPlayServicesAvailability() { checkPlayServicesAvailability() {
if (isIOS) return null; if (isIOS) return null;
const code = this.playServicesAvailability.code; const { code } = this.playServicesAvailability;
if (!this.playServicesAvailability.isAvailable) { if (!this.playServicesAvailability.isAvailable) {
if (INTERNALS.OPTIONS.promptOnMissingPlayServices && this.playServicesAvailability.isUserResolvableError) { if (INTERNALS.OPTIONS.promptOnMissingPlayServices && this.playServicesAvailability.isUserResolvableError) {
@ -63,10 +61,6 @@ export default class RNFirebaseUtils extends ModuleBase {
return FirebaseCoreModule.makePlayServicesAvailable(); return FirebaseCoreModule.makePlayServicesAvailable();
} }
get sharedEventEmitter(): Object {
return INTERNALS.SharedEventEmitter;
}
/** /**
* Set the global logging level for all logs. * Set the global logging level for all logs.
* *
@ -76,30 +70,6 @@ export default class RNFirebaseUtils extends ModuleBase {
INTERNALS.OPTIONS.logLevel = booleanOrDebugString; INTERNALS.OPTIONS.logLevel = booleanOrDebugString;
} }
/**
* Returns an array of all current database registrations id strings
*/
get databaseRegistrations(): Array<string> {
return Object.keys(INTERNALS.SyncTree._reverseLookup);
}
/**
* Call with a registration id string to get the details off this reg
*/
get getDatabaseRegistrationDetails(): Function {
return INTERNALS.SyncTree.getRegistration.bind(INTERNALS.SyncTree);
}
/**
* Accepts an array or a single string of registration ids.
* This will remove the refs on both the js and native sides and their listeners.
* @return {function(this:T)}
*/
get removeDatabaseRegistration(): Function {
return INTERNALS.SyncTree.removeListenersForRegistrations.bind(INTERNALS.SyncTree);
}
/** /**
* Returns props from the android GoogleApiAvailability sdk * Returns props from the android GoogleApiAvailability sdk
* @android * @android
@ -130,7 +100,6 @@ export default class RNFirebaseUtils extends ModuleBase {
export const statics = { export const statics = {
DEFAULT_APP_NAME: INTERNALS.STRINGS.DEFAULT_APP_NAME,
// VERSIONS: { // VERSIONS: {
// react: ReactVersion, // react: ReactVersion,
// 'react-native': Object.values(ReactNativeVersion.version).slice(0, 3).join('.'), // 'react-native': Object.values(ReactNativeVersion.version).slice(0, 3).join('.'),

View File

@ -40,7 +40,18 @@ export type FirebaseError = {
export type FirebaseModule = $Subtype<ModuleBase>; export type FirebaseModule = $Subtype<ModuleBase>;
export type FirebaseModuleName = 'admob' | 'analytics' | 'auth' | 'config' | 'crash' export type FirebaseModuleConfig = {
events?: string[],
moduleName: FirebaseModuleName,
namespace: FirebaseNamespace,
}
export type FirebaseModuleName = 'RNFirebaseAdmob' | 'RNFirebaseAnalytics' | 'RNFirebaseAuth'
| 'RNFirebaseRemoteConfig' | 'RNFirebaseCrash' | 'RNFirebaseCrashlytics' | 'RNFirebaseDatabase'
| 'RNFirebaseFirestore' | 'RNFirebaseLinks' | 'RNFirebaseMessaging' | 'RNFirebasePerformance'
| 'RNFirebaseStorage' | 'RNFirebaseUtils';
export type FirebaseNamespace = 'admob' | 'analytics' | 'auth' | 'config' | 'crash'
| 'crashlytics' | 'database' | 'firestore' | 'links' | 'messaging' | 'perf' | 'storage' | 'crashlytics' | 'database' | 'firestore' | 'links' | 'messaging' | 'perf' | 'storage'
| 'utils'; | 'utils';

View File

@ -1,61 +1,16 @@
/** /**
* @flow * @flow
*/ */
import { NativeModules } from 'react-native'; import { initialiseLogger } from './log';
import { initialiseNativeModule } from './native';
import Log from './log';
import INTERNALS from './internals';
import FirebaseCore from '../modules/core/firebase';
import { nativeWithApp } from '../utils';
import type FirebaseApp from '../modules/core/firebase-app'; import type FirebaseApp from '../modules/core/firebase-app';
import type { FirebaseModuleName } from '../types'; import type { FirebaseModuleConfig } from '../types';
const logs = {};
// Firebase Native SDKs that support multiple app instances
const MULTI_APP_MODULES = [
'auth',
'database',
'firestore',
'storage',
];
const NATIVE_MODULE_EVENTS = {
Storage: [
'storage_event',
'storage_error',
],
Auth: [
'auth_state_changed',
'phone_auth_state_changed',
],
Database: [
'database_transaction_event',
// 'database_server_offset', // TODO
],
Firestore: [
'firestore_collection_sync_event',
'firestore_document_sync_event',
],
};
const DEFAULTS = {
Database: {
persistence: false,
},
};
export default class ModuleBase { export default class ModuleBase {
_native: Object;
_module: string;
_options: Object;
_appName: string;
_namespace: string;
_firebaseApp: FirebaseApp; _firebaseApp: FirebaseApp;
_eventEmitter: Object; _native: Object;
static _NAMESPACE: FirebaseModuleName; _options: Object;
static _NATIVE_MODULE: string;
/** /**
* *
@ -63,59 +18,21 @@ export default class ModuleBase {
* @param options * @param options
* @param withEventEmitter * @param withEventEmitter
*/ */
constructor(firebaseApp: FirebaseApp, options: Object, withEventEmitter: boolean = false) { constructor(firebaseApp: FirebaseApp, options: Object, config: FirebaseModuleConfig) {
this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', ''); if (!config.moduleName) {
throw new Error('Missing module name');
}
if (!config.namespace) {
throw new Error('Missing namespace');
}
const { moduleName } = config;
this._firebaseApp = firebaseApp; this._firebaseApp = firebaseApp;
this._appName = firebaseApp._name; this._options = options;
this._namespace = `${this._appName}:${this._module}`;
this._options = Object.assign({}, DEFAULTS[this._module] || {}, options);
// check if native module exists as all native // check if native module exists as all native
// modules are now optionally part of build // TODO: Get rid of this._native and change to using getNativeModule instead?
const nativeModule = NativeModules[this.constructor._NATIVE_MODULE]; this._native = initialiseNativeModule(this, config);
initialiseLogger(this, `${firebaseApp.name}:${moduleName.replace('RNFirebase', '')}`);
if (!nativeModule && !this.constructor._NATIVE_DISABLED) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(this.constructor._NAMESPACE, this.constructor._NATIVE_MODULE));
}
// used by the modules that extend ModuleBase
// to access their native module counterpart
if (!MULTI_APP_MODULES.includes(this._module.toLowerCase())) {
this._native = nativeModule;
} else {
this._native = nativeWithApp(this._appName, nativeModule);
}
if (withEventEmitter) {
this._setupEventEmitter(nativeModule, this._module);
}
}
/**
*
* @param nativeModule
* @param moduleName
* @private
*/
_setupEventEmitter(nativeModule: Object, moduleName: string) {
this._eventEmitter = FirebaseCore._getOrSetNativeEmitter(`${this._appName}-${this._module}`, nativeModule);
const events = NATIVE_MODULE_EVENTS[moduleName];
if (events && events.length) {
for (let i = 0, len = events.length; i < len; i++) {
FirebaseCore._subscribeForDistribution(events[i], this._eventEmitter);
}
}
}
/**
*
* @param eventName
* @return {string}
* @private
*/
_getAppEventName(eventName: string) {
return `${this._appName}-${eventName}`;
} }
/** /**
@ -125,50 +42,4 @@ export default class ModuleBase {
get app(): FirebaseApp { get app(): FirebaseApp {
return this._firebaseApp; return this._firebaseApp;
} }
get log(): Log {
if (logs[this._namespace]) return logs[this._namespace];
return logs[this._namespace] = Log.createLogger(`🔥 ${this._namespace.toUpperCase()}`);
}
/*
* Proxy functions to shared event emitter instance
* https://github.com/facebook/react-native/blob/master/Libraries/EventEmitter/EventEmitter.js
*/
get sharedEventEmitter(): Object {
return INTERNALS.SharedEventEmitter;
}
get addListener(): Function {
return INTERNALS.SharedEventEmitter.addListener.bind(INTERNALS.SharedEventEmitter);
}
get once(): Function {
return INTERNALS.SharedEventEmitter.once.bind(INTERNALS.SharedEventEmitter);
}
get on(): Function {
return INTERNALS.SharedEventEmitter.addListener.bind(INTERNALS.SharedEventEmitter);
}
get emit(): Function {
return INTERNALS.SharedEventEmitter.emit.bind(INTERNALS.SharedEventEmitter);
}
get listeners(): Function {
return INTERNALS.SharedEventEmitter.listeners.bind(INTERNALS.SharedEventEmitter);
}
hasListeners(eventType: string): Boolean {
const subscriptions = INTERNALS.SharedEventEmitter._subscriber.getSubscriptionsForType(eventType);
return subscriptions && subscriptions.length;
}
get removeListener(): Function {
return INTERNALS.SharedEventEmitter.removeListener.bind(INTERNALS.SharedEventEmitter);
}
get removeAllListeners(): Function {
return INTERNALS.SharedEventEmitter.removeAllListeners.bind(INTERNALS.SharedEventEmitter);
}
} }

View File

@ -1,8 +1,6 @@
/** /**
* @flow * @flow
*/ */
import Log from './log';
import type Database from '../modules/database'; import type Database from '../modules/database';
import type Storage from '../modules/storage'; import type Storage from '../modules/storage';
@ -24,8 +22,4 @@ export default class ReferenceBase {
get key(): string | null { get key(): string | null {
return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1); return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1);
} }
get log(): Log {
return this._module.log;
}
} }

View File

@ -1,9 +1,9 @@
/** /**
* @flow * @flow
*/ */
import { NativeEventEmitter } from 'react-native'; import { NativeEventEmitter, NativeModules } from 'react-native';
import INTERNALS from './internals'; import { SharedEventEmitter } from './events';
import DatabaseSnapshot from '../modules/database/snapshot'; import DatabaseSnapshot from '../modules/database/snapshot';
import DatabaseReference from '../modules/database/reference'; import DatabaseReference from '../modules/database/reference';
import { isString, nativeToJSError } from '../utils'; import { isString, nativeToJSError } from '../utils';
@ -23,21 +23,21 @@ type Registration = {
* Internally used to manage firebase database realtime event * Internally used to manage firebase database realtime event
* subscriptions and keep the listeners in sync in js vs native. * subscriptions and keep the listeners in sync in js vs native.
*/ */
export default class SyncTree { class SyncTree {
_databaseNative: Object;
_nativeEmitter: NativeEventEmitter; _nativeEmitter: NativeEventEmitter;
_reverseLookup: { [string]: Registration }; _reverseLookup: { [string]: Registration };
_tree: { [string]: { [string]: Array }}; _tree: { [string]: { [string]: { [string]: Function }}};
constructor(databaseNative: Object) { constructor() {
this._tree = {}; this._tree = {};
this._reverseLookup = {}; this._reverseLookup = {};
this._databaseNative = databaseNative; if (NativeModules.RNFirebaseDatabase) {
this._nativeEmitter = new NativeEventEmitter(databaseNative); this._nativeEmitter = new NativeEventEmitter(NativeModules.RNFirebaseDatabase);
this._nativeEmitter.addListener( this._nativeEmitter.addListener(
'database_sync_event', 'database_sync_event',
this._handleSyncEvent.bind(this), this._handleSyncEvent.bind(this),
); );
}
} }
/** /**
@ -71,13 +71,13 @@ export default class SyncTree {
// notify native that the registration // notify native that the registration
// no longer exists so it can remove // no longer exists so it can remove
// the native listeners // the native listeners
return this._databaseNative.off(key, eventRegistrationKey); return NativeModules.RNFirebaseDatabase.off(key, eventRegistrationKey);
} }
const { snapshot, previousChildName } = event.data; const { snapshot, previousChildName } = event.data;
// forward on to users .on(successCallback <-- listener // forward on to users .on(successCallback <-- listener
return INTERNALS.SharedEventEmitter.emit( return SharedEventEmitter.emit(
eventRegistrationKey, eventRegistrationKey,
new DatabaseSnapshot(registration.ref, snapshot), new DatabaseSnapshot(registration.ref, snapshot),
previousChildName, previousChildName,
@ -104,7 +104,7 @@ export default class SyncTree {
const error = nativeToJSError(code, message, { ref: registration.ref }); const error = nativeToJSError(code, message, { ref: registration.ref });
// forward on to users .on(successCallback, cancellationCallback <-- listener // forward on to users .on(successCallback, cancellationCallback <-- listener
INTERNALS.SharedEventEmitter.emit(registrationCancellationKey, error); SharedEventEmitter.emit(registrationCancellationKey, error);
// remove the paired event registration - if we received a cancellation // remove the paired event registration - if we received a cancellation
// event then it's guaranteed that they'll be no further value events // event then it's guaranteed that they'll be no further value events
@ -131,14 +131,14 @@ export default class SyncTree {
removeListenersForRegistrations(registrations: string | string[]) { removeListenersForRegistrations(registrations: string | string[]) {
if (isString(registrations)) { if (isString(registrations)) {
this.removeRegistration(registrations); this.removeRegistration(registrations);
INTERNALS.SharedEventEmitter.removeAllListeners(registrations); SharedEventEmitter.removeAllListeners(registrations);
return 1; return 1;
} }
if (!Array.isArray(registrations)) return 0; if (!Array.isArray(registrations)) return 0;
for (let i = 0, len = registrations.length; i < len; i++) { for (let i = 0, len = registrations.length; i < len; i++) {
this.removeRegistration(registrations[i]); this.removeRegistration(registrations[i]);
INTERNALS.SharedEventEmitter.removeAllListeners(registrations[i]); SharedEventEmitter.removeAllListeners(registrations[i]);
} }
return registrations.length; return registrations.length;
@ -157,7 +157,7 @@ export default class SyncTree {
for (let i = 0, len = registrations.length; i < len; i++) { for (let i = 0, len = registrations.length; i < len; i++) {
const registration = registrations[i]; const registration = registrations[i];
const subscriptions = INTERNALS.SharedEventEmitter._subscriber.getSubscriptionsForType(registration); const subscriptions = SharedEventEmitter._subscriber.getSubscriptionsForType(registration);
if (subscriptions) { if (subscriptions) {
for (let j = 0, l = subscriptions.length; j < l; j++) { for (let j = 0, l = subscriptions.length; j < l; j++) {
const subscription = subscriptions[j]; const subscription = subscriptions[j];
@ -251,12 +251,12 @@ export default class SyncTree {
this._reverseLookup[eventRegistrationKey] = Object.assign({ listener }, parameters); this._reverseLookup[eventRegistrationKey] = Object.assign({ listener }, parameters);
if (once) { if (once) {
INTERNALS.SharedEventEmitter.once( SharedEventEmitter.once(
eventRegistrationKey, eventRegistrationKey,
this._onOnceRemoveRegistration(eventRegistrationKey, listener), this._onOnceRemoveRegistration(eventRegistrationKey, listener),
); );
} else { } else {
INTERNALS.SharedEventEmitter.addListener(eventRegistrationKey, listener); SharedEventEmitter.addListener(eventRegistrationKey, listener);
} }
return eventRegistrationKey; return eventRegistrationKey;
@ -287,7 +287,7 @@ export default class SyncTree {
// automatically unsubscribed on native when the first event is sent // automatically unsubscribed on native when the first event is sent
const registrationObj = this._reverseLookup[registration]; const registrationObj = this._reverseLookup[registration];
if (registrationObj && !once) { if (registrationObj && !once) {
this._databaseNative.off(registrationObj.key, registration); NativeModules.RNFirebaseDatabase.off(registrationObj.key, registration);
} }
delete this._tree[path][eventType][registration]; delete this._tree[path][eventType][registration];
@ -311,3 +311,5 @@ export default class SyncTree {
}; };
} }
} }
export default new SyncTree();

171
lib/utils/apps.js Normal file
View File

@ -0,0 +1,171 @@
/**
* @flow
*/
import { NativeModules } from 'react-native';
import FirebaseApp from '../modules/core/firebase-app';
import INTERNALS from './internals';
import { isAndroid, isObject, isString } from './';
import type {
FirebaseModule,
FirebaseModuleAndStatics,
FirebaseModuleName,
FirebaseNamespace,
FirebaseOptions,
FirebaseStatics,
} from '../types';
const FirebaseCoreModule = NativeModules.RNFirebase;
const APPS: { [string]: FirebaseApp } = {};
const APP_MODULES: { [FirebaseApp]: { [string]: FirebaseModule }} = {};
const DEFAULT_APP_NAME = '[DEFAULT]';
export default {
DEFAULT_APP_NAME,
app(name?: string): FirebaseApp {
const _name = name ? name.toUpperCase() : DEFAULT_APP_NAME;
const app = APPS[_name];
if (!app) throw new Error(INTERNALS.STRINGS.ERROR_APP_NOT_INIT(_name));
return app;
},
apps(): Array<FirebaseApp> {
return Object.values(APPS);
},
/**
*
* @param statics
* @param InstanceClass
* @return {function()}
* @private
*/
appModule<M: FirebaseModule>(firebaseApp: FirebaseApp, namespace: FirebaseNamespace, InstanceClass: Class<M>): () => FirebaseModule {
return (): M => {
if (!APP_MODULES[firebaseApp]) {
APP_MODULES[firebaseApp] = {};
}
if (isAndroid && namespace !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) {
INTERNALS.FLAGS.checkedPlayServices = true;
this.utils().checkPlayServicesAvailability();
}
if (!APP_MODULES[firebaseApp][namespace]) {
APP_MODULES[firebaseApp][namespace] = new InstanceClass(firebaseApp, firebaseApp.options);
}
return APP_MODULES[firebaseApp][namespace];
};
},
deleteApp(name: string): Promise<boolean> {
const app = APPS[name];
if (!app) return Promise.resolve(true);
// https://firebase.google.com/docs/reference/js/firebase.app.App#delete
return app.delete().then(() => {
delete APPS[name];
return true;
});
},
/**
* Web SDK initializeApp
*
* @param options
* @param name
* @return {*}
*/
initializeApp(options: FirebaseOptions, name: string): FirebaseApp {
if (name && !isString(name)) {
throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME);
}
const _name = (name || DEFAULT_APP_NAME).toUpperCase();
// return an existing app if found
// todo in v4 remove deprecation and throw an error
if (APPS[_name]) {
console.warn(INTERNALS.STRINGS.WARN_INITIALIZE_DEPRECATION);
return APPS[_name];
}
// only validate if app doesn't already exist
// to allow apps already initialized natively
// to still go through init without erroring (backwards compatibility)
if (!isObject(options)) {
throw new Error(INTERNALS.STRINGS.ERROR_INIT_OBJECT);
}
if (!options.apiKey) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('apiKey'));
}
if (!options.appId) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('appId'));
}
if (!options.databaseURL) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('databaseURL'));
}
if (!options.messagingSenderId) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('messagingSenderId'));
}
if (!options.projectId) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('projectId'));
}
if (!options.storageBucket) {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('storageBucket'));
}
APPS[_name] = new FirebaseApp(_name, options);
return APPS[_name];
},
/**
* Bootstraps all native app instances that were discovered on boot
*/
initializeNativeApps() {
for (let i = 0, len = FirebaseCoreModule.apps.length; i < len; i++) {
const app = FirebaseCoreModule.apps[i];
const options = Object.assign({}, app);
delete options.name;
APPS[app.name] = new FirebaseApp(app.name, options, true);
}
},
/**
*
* @param statics
* @param InstanceClass
* @return {function(FirebaseApp=)}
*/
moduleAndStatics<M: FirebaseModule, S: FirebaseStatics>(namespace: FirebaseNamespace, statics: S, moduleName: FirebaseModuleName): FirebaseModuleAndStatics<M, S> {
const getModule = (app?: FirebaseApp): FirebaseModule => {
let firebaseApp = app;
// throw an error if it's not a valid app instance
if (firebaseApp && !(firebaseApp instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace));
// default to the 'DEFAULT' app if no arg provided - will throw an error
// if default app not initialized
else if (!firebaseApp) firebaseApp = this.app(DEFAULT_APP_NAME);
if (namespace === 'crashlytics') {
return firebaseApp.fabric[namespace]();
}
const module = firebaseApp[namespace];
return module();
};
return Object.assign(getModule, statics, {
nativeModuleExists: !!NativeModules[moduleName],
});
},
};

62
lib/utils/events.js Normal file
View File

@ -0,0 +1,62 @@
/**
* @flow
*/
import { NativeEventEmitter, NativeModules } from 'react-native';
import EventEmitter from './emitter/EventEmitter';
import type ModuleBase from './ModuleBase';
import type { FirebaseModuleConfig, FirebaseModuleName } from '../types';
const NATIVE_EMITTERS: { [string]: NativeEventEmitter } = {};
const NATIVE_SUBSCRIPTIONS: { [string]: boolean } = {};
export const SharedEventEmitter = new EventEmitter();
export const getAppEventName = (module: ModuleBase, eventName: string): string => {
return `${module._firebaseApp._name}-${eventName}`;
};
const getNativeEmitter = (moduleName: FirebaseModuleName, module: ModuleBase): NativeEventEmitter => {
const name = `${module.app.name}-${moduleName}`;
const nativeModule = NativeModules[moduleName];
if (!NATIVE_EMITTERS[name]) {
NATIVE_EMITTERS[name] = new NativeEventEmitter(nativeModule);
}
return NATIVE_EMITTERS[name];
};
/**
* Subscribe to a native event for js side distribution by appName
* React Native events are hard set at compile - cant do dynamic event names
* so we use a single event send it to js and js then internally can prefix it
* and distribute dynamically.
*
* @param module
* @param eventName
* @private
*/
const subscribeToNativeModuleEvents = (moduleName: FirebaseModuleName, module: ModuleBase, eventName: string): void => {
if (!NATIVE_SUBSCRIPTIONS[eventName]) {
const nativeEmitter = getNativeEmitter(moduleName, module);
nativeEmitter.addListener(eventName, (event) => {
if (event.appName) {
// native event has an appName property - auto prefix and internally emit
SharedEventEmitter.emit(`${event.appName}-${eventName}`, event);
} else {
// standard event - no need to prefix
SharedEventEmitter.emit(eventName, event);
}
});
NATIVE_SUBSCRIPTIONS[eventName] = true;
}
};
export const initialiseNativeModuleEventEmitter = (module: ModuleBase, config: FirebaseModuleConfig): void => {
const { events, moduleName } = config;
if (events && events.length) {
for (let i = 0, len = events.length; i < len; i++) {
subscribeToNativeModuleEvents(moduleName, module, events[i]);
}
}
};

View File

@ -340,25 +340,6 @@ export function nativeToJSError(code: string, message: string, additionalProps?:
return error; return error;
} }
/**
* Prepends appName arg to all native method calls
* @param appName
* @param NativeModule
*/
export function nativeWithApp(appName: string, NativeModule: Object) {
const native = {};
const methods = Object.keys(NativeModule);
for (let i = 0, len = methods.length; i < len; i++) {
const method = methods[i];
native[method] = (...args) => {
return NativeModule[method](...[appName, ...args]);
};
}
return native;
}
/** /**
* *
* @param object * @param object

View File

@ -1,15 +1,7 @@
/** /**
* @flow * @flow
*/ */
import { Platform, NativeModules } from 'react-native'; import { Platform } from 'react-native';
import EventEmitter from './emitter/EventEmitter';
import ModuleBase from './ModuleBase';
import SyncTree from './SyncTree';
import type FirebaseApp from '../modules/core/firebase-app';
const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]';
const NAMESPACE_PODS = { const NAMESPACE_PODS = {
admob: 'Firebase/AdMob', admob: 'Firebase/AdMob',
@ -55,8 +47,6 @@ const PLAY_SERVICES_CODES = {
}, },
}; };
const APPS: { [string]: FirebaseApp } = {};
export default { export default {
// default options // default options
OPTIONS: { OPTIONS: {
@ -69,9 +59,6 @@ export default {
checkedPlayServices: false, checkedPlayServices: false,
}, },
// track all initialized firebase apps
APPS,
STRINGS: { STRINGS: {
WARN_INITIALIZE_DEPRECATION: 'Deprecation: Calling \'initializeApp()\' for apps that are already initialised natively ' + WARN_INITIALIZE_DEPRECATION: 'Deprecation: Calling \'initializeApp()\' for apps that are already initialised natively ' +
'is unnecessary, use \'firebase.app()\' instead to access the already initialized default app instance.', 'is unnecessary, use \'firebase.app()\' instead to access the already initialized default app instance.',
@ -194,8 +181,8 @@ export default {
/** /**
* @return {string} * @return {string}
*/ */
ERROR_UNSUPPORTED_MODULE_METHOD(module: Class<ModuleBase>, method: string) { ERROR_UNSUPPORTED_MODULE_METHOD(namespace: string, method: string) {
return `firebase.${module._NAMESPACE}().${method}() is unsupported by the native Firebase SDKs.`; return `firebase.${namespace}().${method}() is unsupported by the native Firebase SDKs.`;
}, },
@ -222,24 +209,5 @@ export default {
'For more information on how to resolve this issue, configure Play Services checks or for guides on how to validate Play Services on your users devices see the link below:' + 'For more information on how to resolve this issue, configure Play Services checks or for guides on how to validate Play Services on your users devices see the link below:' +
'\r\n\r\nhttp://invertase.link/play-services'; '\r\n\r\nhttp://invertase.link/play-services';
}, },
DEFAULT_APP_NAME,
},
SharedEventEmitter: new EventEmitter(),
SyncTree: NativeModules.RNFirebaseDatabase ? new SyncTree(NativeModules.RNFirebaseDatabase) : null,
// internal utils
deleteApp(name: String): Promise<boolean> {
const app = this.APPS[name];
if (!app) return Promise.resolve(true);
// https://firebase.google.com/docs/reference/js/firebase.app.App#delete
return app.delete().then(() => {
delete this.APPS[name];
return true;
});
}, },
}; };

View File

@ -1,5 +1,10 @@
/*
* @flow
*/
import { windowOrGlobal } from './'; import { windowOrGlobal } from './';
import type ModuleBase from './ModuleBase';
((base) => { ((base) => {
window = base || window; window = base || window;
if (!window.localStorage) window.localStorage = {}; if (!window.localStorage) window.localStorage = {};
@ -7,6 +12,16 @@ import { windowOrGlobal } from './';
// clean up time // clean up time
const NATIVE_LOGGERS: { [ModuleBase]: Object } = {};
export const getLogger = (module: ModuleBase) => NATIVE_LOGGERS[module];
export const initialiseLogger = (module: ModuleBase, logNamespace: string) => {
if (!NATIVE_LOGGERS[module]) {
NATIVE_LOGGERS[module] = require('bows')(`🔥 ${logNamespace.toUpperCase()}`);
}
};
export default class Log { export default class Log {
static createLogger(namespace) { static createLogger(namespace) {
return require('bows')(namespace); return require('bows')(namespace);

63
lib/utils/native.js Normal file
View File

@ -0,0 +1,63 @@
/*
* @flow
*/
import { NativeModules } from 'react-native';
import { initialiseNativeModuleEventEmitter } from './events';
import INTERNALS from './internals';
import type ModuleBase from './ModuleBase';
import type { FirebaseModuleConfig } from '../types';
// Firebase Native SDKs that support multiple app instances
const MULTI_APP_MODULES = [
'RNFirebaseAuth',
'RNFirebaseDatabase',
'RNFirebaseFirestore',
'RNFirebaseStorage',
];
const NATIVE_MODULES: { [ModuleBase]: Object } = {};
/**
* Prepends appName arg to all native method calls
* @param appName
* @param NativeModule
*/
const nativeWithApp = (appName: string, NativeModule: Object): Object => {
const native = {};
const methods = Object.keys(NativeModule);
for (let i = 0, len = methods.length; i < len; i++) {
const method = methods[i];
native[method] = (...args) => {
return NativeModule[method](...[appName, ...args]);
};
}
return native;
};
export const getNativeModule = (module: ModuleBase): Object => {
return NATIVE_MODULES[module];
};
export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModuleConfig): Object => {
const { moduleName, namespace } = config;
const nativeModule = NativeModules[moduleName];
if (!nativeModule && namespace !== 'utils') {
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(namespace, moduleName));
}
// used by the modules that extend ModuleBase
// to access their native module counterpart
if (!MULTI_APP_MODULES.includes(moduleName)) {
NATIVE_MODULES[module] = nativeModule;
} else {
NATIVE_MODULES[module] = nativeWithApp(module.app.name, nativeModule);
}
initialiseNativeModuleEventEmitter(module, config);
return NATIVE_MODULES[module];
};

View File

@ -153,7 +153,7 @@ PODS:
- React/Core - React/Core
- React/fishhook - React/fishhook
- React/RCTBlob - React/RCTBlob
- RNFirebase (3.1.1): - RNFirebase (3.2.0):
- React - React
- yoga (0.49.1.React) - yoga (0.49.1.React)
@ -215,7 +215,7 @@ SPEC CHECKSUMS:
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8 Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8
React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee
RNFirebase: 976f3b35d112017c69da5ada20cf1f15fc2c327e RNFirebase: 22b1917fec663706907bc901ed665ac4f8b9bfd6
yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a
PODFILE CHECKSUM: f17a538903249834df5049668d10174810db4c4c PODFILE CHECKSUM: f17a538903249834df5049668d10174810db4c4c

View File

@ -40,7 +40,7 @@ const ios = {
const instances = { const instances = {
web: firebase.initializeApp(config), web: firebase.initializeApp(config),
native: RNfirebase.app(), native: RNfirebase,
another: RNfirebase.initializeApp(Platform.OS === 'ios' ? ios : android, 'anotherApp'), another: RNfirebase.initializeApp(Platform.OS === 'ios' ? ios : android, 'anotherApp'),
}; };

View File

@ -53,8 +53,7 @@ function coreTests({ describe, it }) {
it('it should provide an array of apps', () => { it('it should provide an array of apps', () => {
should.equal(!!RNFirebase.apps.length, true); should.equal(!!RNFirebase.apps.length, true);
should.equal(RNFirebase.apps[0]._name, RNFirebase.utils.DEFAULT_APP_NAME); should.equal(RNFirebase.apps.includes(RNFirebase.app('[DEFAULT]')), true);
should.equal(RNFirebase.apps[0].name, '[DEFAULT]');
return Promise.resolve(); return Promise.resolve();
}); });