Merge branch 'firestore-transactions' of https://github.com/invertase/react-native-firebase into firestore-transactions
This commit is contained in:
commit
cc1117f878
|
@ -50,7 +50,7 @@ module.system=haste
|
|||
|
||||
emoji=true
|
||||
|
||||
munge_underscores=false
|
||||
munge_underscores=true
|
||||
|
||||
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
|
||||
|
||||
|
@ -69,6 +69,7 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1
|
|||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowBug.*
|
||||
|
||||
unsafe.enable_getters_and_setters=true
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
<!---
|
||||
- BEFORE YOU MAKE AN ISSUE -
|
||||
-->
|
||||
BEFORE YOU MAKE AN ISSUE
|
||||
|
||||
<!---
|
||||
1) If you're trying to request a feature then please do so via our request board:
|
||||
https://react-native-firebase.canny.io/feature-requests
|
||||
--->
|
||||
The issue list of this repo is exclusively for bug reports.
|
||||
|
||||
<!---
|
||||
2) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed.
|
||||
1) For feature requests, please use our Canny board: https://react-native-firebase.canny.io/feature-requests
|
||||
|
||||
2) For questions and support please use our Discord chat: https://discord.gg/t6bdqMs or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase
|
||||
|
||||
3) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed.
|
||||
-->
|
||||
|
||||
### Issue
|
||||
|
@ -38,4 +37,4 @@
|
|||
6. Firebase Module:
|
||||
|
||||
<!-- Love react-native-firebase? Please consider supporting our collective:
|
||||
👉 https://opencollective.com/react-native-firebase/donate -->
|
||||
👉 https://opencollective.com/react-native-firebase/donate -->
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#import "RNFirebase.h"
|
||||
#import "RNFirebaseUtil.h"
|
||||
#import <FirebaseCore/FirebaseCore.h>
|
||||
|
||||
@implementation RNFirebase
|
||||
|
@ -21,14 +22,14 @@ RCT_EXPORT_MODULE(RNFirebase);
|
|||
* @return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(initializeApp:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
options:
|
||||
(NSDictionary *) options
|
||||
callback:
|
||||
(RCTResponseSenderBlock) callback) {
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
FIRApp *existingApp = [FIRApp appNamed:appName];
|
||||
FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
if (!existingApp) {
|
||||
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.bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
|
||||
|
||||
NSString *appName = [RNFirebaseUtil getAppName:appDisplayName];
|
||||
[FIRApp configureWithName:appName options:firOptions];
|
||||
}
|
||||
|
||||
|
@ -55,13 +57,13 @@ RCT_EXPORT_METHOD(initializeApp:
|
|||
* @return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(deleteApp:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
|
||||
FIRApp *existingApp = [FIRApp appNamed:appName];
|
||||
FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
if (!existingApp) {
|
||||
return resolve([NSNull null]);
|
||||
|
@ -90,7 +92,7 @@ RCT_EXPORT_METHOD(deleteApp:
|
|||
NSMutableDictionary *appOptions = [NSMutableDictionary new];
|
||||
FIRApp *firApp = firApps[key];
|
||||
FIROptions *firOptions = [firApp options];
|
||||
appOptions[@"name"] = firApp.name;
|
||||
appOptions[@"name"] = [RNFirebaseUtil getAppDisplayName:firApp.name];
|
||||
appOptions[@"apiKey"] = firOptions.APIKey;
|
||||
appOptions[@"appId"] = firOptions.googleAppID;
|
||||
appOptions[@"databaseURL"] = firOptions.databaseURL;
|
||||
|
|
|
@ -3,11 +3,15 @@
|
|||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <React/RCTEventEmitter.h>
|
||||
#import <Firebase.h>
|
||||
|
||||
@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)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
|
||||
|
||||
|
|
|
@ -2,6 +2,28 @@
|
|||
|
||||
@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 {
|
||||
@try {
|
||||
// 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
|
||||
NSMutableDictionary *newBody = [body mutableCopy];
|
||||
newBody[@"appName"] = appName;
|
||||
newBody[@"appName"] = [RNFirebaseUtil getAppDisplayName:app.name];
|
||||
|
||||
[RNFirebaseUtil sendJSEvent:emitter name:name body:newBody];
|
||||
}
|
||||
|
|
|
@ -23,19 +23,19 @@ RCT_EXPORT_MODULE();
|
|||
|
||||
*/
|
||||
RCT_EXPORT_METHOD(addAuthStateListener:
|
||||
(NSString *) appName) {
|
||||
(NSString *) appDisplayName) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
if (![_authStateHandlers valueForKey:appName]) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
if (![_authStateHandlers valueForKey:firApp.name]) {
|
||||
FIRAuthStateDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) {
|
||||
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 {
|
||||
[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:
|
||||
(NSString *) appName) {
|
||||
(NSString *) appDisplayName) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
if ([_authStateHandlers valueForKey:appName]) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
[[FIRAuth authWithApp:firApp] removeAuthStateDidChangeListener:[_authStateHandlers valueForKey:appName]];
|
||||
[_authStateHandlers removeObjectForKey:appName];
|
||||
if ([_authStateHandlers valueForKey:firApp.name]) {
|
||||
[[FIRAuth authWithApp:firApp] removeAuthStateDidChangeListener:[_authStateHandlers valueForKey:firApp.name]];
|
||||
[_authStateHandlers removeObjectForKey:firApp.name];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,19 +58,19 @@ RCT_EXPORT_METHOD(removeAuthStateListener:
|
|||
|
||||
*/
|
||||
RCT_EXPORT_METHOD(addIdTokenListener:
|
||||
(NSString *) appName) {
|
||||
(NSString *) appDisplayName) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
if (![_idTokenHandlers valueForKey:appName]) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
if (![_idTokenHandlers valueForKey:firApp.name]) {
|
||||
FIRIDTokenDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addIDTokenDidChangeListener:^(FIRAuth * _Nonnull auth, FIRUser * _Nullable user) {
|
||||
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 {
|
||||
[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:
|
||||
(NSString *) appName) {
|
||||
if ([_idTokenHandlers valueForKey:appName]) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
[[FIRAuth authWithApp:firApp] removeIDTokenDidChangeListener:[_idTokenHandlers valueForKey:appName]];
|
||||
[_idTokenHandlers removeObjectForKey:appName];
|
||||
(NSString *) appDisplayName) {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
if ([_idTokenHandlers valueForKey:firApp.name]) {
|
||||
[[FIRAuth authWithApp:firApp] removeIDTokenDidChangeListener:[_idTokenHandlers valueForKey:firApp.name]];
|
||||
[_idTokenHandlers removeObjectForKey:firApp.name];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,12 +98,12 @@ RCT_EXPORT_METHOD(removeIdTokenListener:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signOut:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
|
@ -125,12 +126,12 @@ RCT_EXPORT_METHOD(signOut:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signInAnonymously:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInAnonymouslyWithCompletion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
|
@ -152,7 +153,7 @@ RCT_EXPORT_METHOD(signInAnonymously:
|
|||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signInWithEmailAndPassword:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
email:
|
||||
(NSString *) email
|
||||
pass:
|
||||
|
@ -161,7 +162,7 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword:
|
|||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInWithEmail:email password:password completion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
|
@ -182,7 +183,7 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword:
|
|||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(createUserWithEmailAndPassword:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
email:
|
||||
(NSString *) email
|
||||
pass:
|
||||
|
@ -191,7 +192,7 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword:
|
|||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] createUserWithEmail:email password:password completion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
|
@ -210,12 +211,12 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword:
|
|||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(delete:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
if (user) {
|
||||
|
@ -239,12 +240,12 @@ RCT_EXPORT_METHOD(delete:
|
|||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(reload:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
|
@ -262,11 +263,11 @@ RCT_EXPORT_METHOD(reload:
|
|||
@param RCTPromiseRejectBlock reject
|
||||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appDisplayName
|
||||
actionCodeSettings:(NSDictionary *) actionCodeSettings
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
if (user) {
|
||||
|
@ -298,14 +299,14 @@ RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appName
|
|||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(updateEmail:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
email:
|
||||
(NSString *) email
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
if (user) {
|
||||
|
@ -330,14 +331,14 @@ RCT_EXPORT_METHOD(updateEmail:
|
|||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(updatePassword:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
password:
|
||||
(NSString *) password
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
|
@ -364,14 +365,14 @@ RCT_EXPORT_METHOD(updatePassword:
|
|||
@return return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(updateProfile:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
props:
|
||||
(NSDictionary *) props
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
|
@ -412,14 +413,14 @@ RCT_EXPORT_METHOD(updateProfile:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(getToken:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
forceRefresh:
|
||||
(BOOL) forceRefresh
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
|
@ -447,7 +448,7 @@ RCT_EXPORT_METHOD(getToken:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signInWithCredential:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
provider:
|
||||
(NSString *) provider
|
||||
token:
|
||||
|
@ -458,7 +459,7 @@ RCT_EXPORT_METHOD(signInWithCredential:
|
|||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
|
||||
|
@ -485,7 +486,7 @@ RCT_EXPORT_METHOD(signInWithCredential:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(confirmPasswordReset:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
code:
|
||||
(NSString *) code
|
||||
newPassword:
|
||||
|
@ -494,8 +495,8 @@ RCT_EXPORT_METHOD(confirmPasswordReset:
|
|||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] confirmPasswordResetWithCode:code newPassword:newPassword completion:^(NSError *_Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
|
@ -515,15 +516,15 @@ RCT_EXPORT_METHOD(confirmPasswordReset:
|
|||
* @return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(applyActionCode:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
code:
|
||||
(NSString *) code
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] applyActionCode:code completion:^(NSError *_Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
|
@ -542,15 +543,15 @@ RCT_EXPORT_METHOD(applyActionCode:
|
|||
* @return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(checkActionCode:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
code:
|
||||
(NSString *) code
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] checkActionCode:code completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) {
|
||||
if (error) {
|
||||
[self promiseRejectAuthException:reject error:error];
|
||||
|
@ -586,12 +587,12 @@ RCT_EXPORT_METHOD(checkActionCode:
|
|||
@param RCTPromiseRejectBlock reject
|
||||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appDisplayName
|
||||
email:(NSString *) email
|
||||
actionCodeSettings:(NSDictionary *) actionCodeSettings
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
id handler = ^(NSError *_Nullable error) {
|
||||
if (error) {
|
||||
|
@ -600,7 +601,7 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName
|
|||
[self promiseNoUser:resolve rejecter:reject isError:NO];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (actionCodeSettings) {
|
||||
FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings];
|
||||
[[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email actionCodeSettings:settings completion:handler];
|
||||
|
@ -617,12 +618,12 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(getCurrentUser:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
[self promiseWithUser:resolve rejecter:reject user:user];
|
||||
|
@ -637,14 +638,14 @@ RCT_EXPORT_METHOD(getCurrentUser:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signInWithCustomToken:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
customToken:
|
||||
(NSString *) customToken
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
[[FIRAuth authWithApp:firApp] signInWithCustomToken:customToken completion:^(FIRUser *user, NSError *error) {
|
||||
if (error) {
|
||||
|
@ -663,11 +664,11 @@ RCT_EXPORT_METHOD(signInWithCustomToken:
|
|||
@param RCTPromiseRejectBlock reject
|
||||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appDisplayName
|
||||
phoneNumber:(NSString *) phoneNumber
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
if (error) {
|
||||
|
@ -684,17 +685,17 @@ RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appName
|
|||
|
||||
/**
|
||||
verifyPhoneNumber
|
||||
|
||||
|
||||
@param string phoneNumber
|
||||
@param RCTPromiseResolveBlock resolve
|
||||
@param RCTPromiseRejectBlock reject
|
||||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appDisplayName
|
||||
phoneNumber:(NSString *) phoneNumber
|
||||
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) {
|
||||
if (error) {
|
||||
NSDictionary * jsError = [self getJSError:(error)];
|
||||
|
@ -703,7 +704,7 @@ RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName
|
|||
@"requestKey":requestKey,
|
||||
@"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 {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:verificationID forKey:@"authVerificationID"];
|
||||
|
@ -712,16 +713,16 @@ RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName
|
|||
@"requestKey":requestKey,
|
||||
@"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
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSString *verificationId = [defaults stringForKey:@"authVerificationID"];
|
||||
FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationId verificationCode:verificationCode];
|
||||
|
@ -746,7 +747,7 @@ RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appName
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(link:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
provider:
|
||||
(NSString *) provider
|
||||
authToken:
|
||||
|
@ -757,7 +758,7 @@ RCT_EXPORT_METHOD(link:
|
|||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
|
||||
|
@ -791,14 +792,14 @@ RCT_EXPORT_METHOD(link:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(unlink:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
providerId:
|
||||
(NSString *) providerId
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
FIRUser *user = [FIRAuth authWithApp:firApp].currentUser;
|
||||
|
||||
if (user) {
|
||||
|
@ -825,7 +826,7 @@ RCT_EXPORT_METHOD(unlink:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(reauthenticate:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
provider:
|
||||
(NSString *) provider
|
||||
authToken:
|
||||
|
@ -836,7 +837,7 @@ RCT_EXPORT_METHOD(reauthenticate:
|
|||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRApp *firApp = [FIRApp appNamed:appName];
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
|
||||
FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret];
|
||||
|
||||
|
@ -869,14 +870,14 @@ RCT_EXPORT_METHOD(reauthenticate:
|
|||
@return
|
||||
*/
|
||||
RCT_EXPORT_METHOD(fetchProvidersForEmail:
|
||||
(NSString *) appName
|
||||
(NSString *) appDisplayName
|
||||
email:
|
||||
(NSString *) email
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(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) {
|
||||
if (error) {
|
||||
|
@ -962,14 +963,14 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
|
|||
|
||||
/**
|
||||
Reject a promise with an auth exception
|
||||
|
||||
|
||||
@param error NSError
|
||||
*/
|
||||
- (NSDictionary *)getJSError:(NSError *)error {
|
||||
NSString *code = @"auth/unknown";
|
||||
NSString *message = [error localizedDescription];
|
||||
NSString *nativeErrorMessage = [error localizedDescription];
|
||||
|
||||
|
||||
switch (error.code) {
|
||||
case FIRAuthErrorCodeInvalidCustomToken:
|
||||
code = @"auth/invalid-custom-token";
|
||||
|
@ -1043,7 +1044,7 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
|
|||
code = @"auth/internal-error";
|
||||
message = @"An internal error has occurred, please try again.";
|
||||
break;
|
||||
|
||||
|
||||
// unsure of the below codes so leaving them as the default error message
|
||||
case FIRAuthErrorCodeTooManyRequests:
|
||||
code = @"auth/too-many-requests";
|
||||
|
@ -1078,7 +1079,7 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail:
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return @{
|
||||
@"code": code,
|
||||
@"message": message,
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
+ (void)handlePromise:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject databaseError:(NSError *)databaseError;
|
||||
|
||||
+ (FIRDatabase *)getDatabaseForApp:(NSString *)appName;
|
||||
+ (FIRDatabase *)getDatabaseForApp:(NSString *)appDisplayName;
|
||||
|
||||
+ (NSDictionary *)getJSError:(NSError *)nativeError;
|
||||
|
||||
|
|
|
@ -22,38 +22,38 @@ RCT_EXPORT_MODULE();
|
|||
return self;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(goOnline:(NSString *) appName) {
|
||||
[[RNFirebaseDatabase getDatabaseForApp:appName] goOnline];
|
||||
RCT_EXPORT_METHOD(goOnline:(NSString *) appDisplayName) {
|
||||
[[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOnline];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(goOffline:(NSString *) appName) {
|
||||
[[RNFirebaseDatabase getDatabaseForApp:appName] goOffline];
|
||||
RCT_EXPORT_METHOD(goOffline:(NSString *) appDisplayName) {
|
||||
[[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOffline];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setPersistence:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(setPersistence:(NSString *) appDisplayName
|
||||
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) {
|
||||
[RNFirebaseDatabase getDatabaseForApp:appName].persistenceCacheSizeBytes = (NSUInteger)size;
|
||||
[RNFirebaseDatabase getDatabaseForApp:appDisplayName].persistenceCacheSizeBytes = (NSUInteger)size;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) {
|
||||
[FIRDatabase setLoggingEnabled:enabled];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(keepSynced:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(keepSynced:(NSString *) appDisplayName
|
||||
key:(NSString *) key
|
||||
path:(NSString *) path
|
||||
modifiers:(NSArray *) modifiers
|
||||
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];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appDisplayName
|
||||
transactionId:(nonnull NSNumber *) transactionId
|
||||
updates:(NSDictionary *) updates) {
|
||||
__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
|
||||
transactionId:(nonnull NSNumber *) transactionId
|
||||
applyLocally:(BOOL) applyLocally) {
|
||||
|
@ -90,13 +90,13 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName
|
|||
NSMutableDictionary *transactionState = [NSMutableDictionary new];
|
||||
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
|
||||
transactionState[@"semaphore"] = sema;
|
||||
FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path];
|
||||
FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path];
|
||||
|
||||
[ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData *
|
||||
_Nonnull currentData) {
|
||||
dispatch_barrier_async(_transactionQueue, ^{
|
||||
[_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];
|
||||
});
|
||||
|
||||
|
@ -123,7 +123,7 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName
|
|||
}
|
||||
andCompletionBlock:
|
||||
^(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];
|
||||
}
|
||||
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
|
||||
props:(NSDictionary *) props
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
props:(NSDictionary *) props
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(set:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(set:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
props:(NSDictionary *) props
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setPriority:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(setPriority:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
priority:(NSDictionary *) priority
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setWithPriority:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(setWithPriority:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
data:(NSDictionary *) data
|
||||
priority:(NSDictionary *) priority
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(update:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(update:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
props:(NSDictionary *) props
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(remove:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(remove:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(once:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(once:(NSString *) appDisplayName
|
||||
key:(NSString *) key
|
||||
path:(NSString *) path
|
||||
modifiers:(NSArray *) modifiers
|
||||
eventName:(NSString *) eventName
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(on:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(on:(NSString *) appDisplayName
|
||||
props:(NSDictionary *) props) {
|
||||
RNFirebaseDatabaseReference *ref = [self getCachedInternalReferenceForApp:appName props:props];
|
||||
RNFirebaseDatabaseReference *ref = [self getCachedInternalReferenceForApp:appDisplayName props:props];
|
||||
[ref on:props[@"eventType"] registration:props[@"registration"]];
|
||||
}
|
||||
|
||||
|
@ -271,20 +271,20 @@ RCT_EXPORT_METHOD(off:(NSString *) key
|
|||
}
|
||||
}
|
||||
|
||||
+ (FIRDatabase *)getDatabaseForApp:(NSString *)appName {
|
||||
FIRApp *app = [FIRApp appNamed:appName];
|
||||
+ (FIRDatabase *)getDatabaseForApp:(NSString *)appDisplayName {
|
||||
FIRApp *app = [RNFirebaseUtil getApp:appDisplayName];
|
||||
return [FIRDatabase databaseForApp:app];
|
||||
}
|
||||
|
||||
- (FIRDatabaseReference *)getReferenceForAppPath:(NSString *)appName path:(NSString *)path {
|
||||
return [[RNFirebaseDatabase getDatabaseForApp:appName] referenceWithPath:path];
|
||||
- (FIRDatabaseReference *)getReferenceForAppPath:(NSString *)appDisplayName path:(NSString *)path {
|
||||
return [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] referenceWithPath:path];
|
||||
}
|
||||
|
||||
- (RNFirebaseDatabaseReference *)getInternalReferenceForApp:(NSString *)appName key:(NSString *)key path:(NSString *)path modifiers:(NSArray *)modifiers {
|
||||
return [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self app:appName key:key refPath:path modifiers:modifiers];
|
||||
- (RNFirebaseDatabaseReference *)getInternalReferenceForApp:(NSString *)appDisplayName key:(NSString *)key path:(NSString *)path modifiers:(NSArray *)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 *path = props[@"path"];
|
||||
NSDictionary *modifiers = props[@"modifiers"];
|
||||
|
@ -292,7 +292,7 @@ RCT_EXPORT_METHOD(off:(NSString *) key
|
|||
RNFirebaseDatabaseReference *ref = _dbReferences[key];
|
||||
|
||||
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;
|
||||
}
|
||||
return ref;
|
||||
|
@ -380,20 +380,20 @@ RCT_EXPORT_METHOD(off:(NSString *) key
|
|||
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];
|
||||
[updatesMap setValue:transactionId forKey:@"id"];
|
||||
[updatesMap setValue:@"update" forKey:@"type"];
|
||||
[updatesMap setValue:appName forKey:@"appName"];
|
||||
[updatesMap setValue:appDisplayName forKey:@"appName"];
|
||||
[updatesMap setValue:updatesData.value forKey:@"value"];
|
||||
|
||||
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];
|
||||
[resultMap setValue:transactionId forKey:@"id"];
|
||||
[resultMap setValue:appName forKey:@"appName"];
|
||||
[resultMap setValue:appDisplayName forKey:@"appName"];
|
||||
// TODO: no timeout on iOS
|
||||
[resultMap setValue:@(committed) forKey:@"committed"];
|
||||
// TODO: no interrupted on iOS
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
@interface RNFirebaseDatabaseReference : NSObject
|
||||
@property RCTEventEmitter *emitter;
|
||||
@property FIRDatabaseQuery *query;
|
||||
@property NSString *app;
|
||||
@property NSString *appDisplayName;
|
||||
@property NSString *key;
|
||||
@property NSString *path;
|
||||
@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)once:(NSString *) eventType resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
- (void)removeEventListener:(NSString *)eventRegistrationKey;
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
#if __has_include(<FirebaseDatabase/FIRDatabase.h>)
|
||||
|
||||
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter
|
||||
app:(NSString *) app
|
||||
appDisplayName:(NSString *) appDisplayName
|
||||
key:(NSString *) key
|
||||
refPath:(NSString *) refPath
|
||||
modifiers:(NSArray *) modifiers {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_emitter = emitter;
|
||||
_app = app;
|
||||
_appDisplayName = appDisplayName;
|
||||
_key = key;
|
||||
_path = refPath;
|
||||
_listeners = [[NSMutableDictionary alloc] init];
|
||||
|
@ -123,7 +123,7 @@
|
|||
|
||||
- (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(NSString *) path
|
||||
modifiers:(NSArray *)modifiers {
|
||||
FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_app];
|
||||
FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_appDisplayName];
|
||||
FIRDatabaseQuery *query = [[firebaseDatabase reference] child:path];
|
||||
|
||||
for (NSDictionary *modifier in modifiers) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
+ (void)promiseRejectException:(RCTPromiseRejectBlock)reject error:(NSError *)error;
|
||||
|
||||
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appName;
|
||||
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appDisplayName;
|
||||
+ (NSDictionary *)getJSError:(NSError *)nativeError;
|
||||
|
||||
@end
|
||||
|
|
|
@ -22,17 +22,17 @@ RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) {
|
|||
[FIRFirestore enableLogging:enabled];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(collectionGet:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(collectionGet:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
filters:(NSArray *) filters
|
||||
orders:(NSArray *) orders
|
||||
options:(NSDictionary *) options
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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
|
||||
filters:(NSArray *) filters
|
||||
orders:(NSArray *) orders
|
||||
|
@ -41,22 +41,22 @@ RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *) appName
|
|||
[RNFirebaseFirestoreCollectionReference offSnapshot:listenerId];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(collectionOnSnapshot:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(collectionOnSnapshot:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
filters:(NSArray *) filters
|
||||
orders:(NSArray *) orders
|
||||
options:(NSDictionary *) options
|
||||
listenerId:(nonnull NSString *) listenerId
|
||||
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];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(documentBatch:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(documentBatch:(NSString *) appDisplayName
|
||||
writes:(NSArray *) writes
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appName];
|
||||
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appDisplayName];
|
||||
FIRWriteBatch *batch = [firestore batch];
|
||||
|
||||
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
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
// Not supported on iOS out of the box
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(documentOffSnapshot:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(documentOffSnapshot:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
listenerId:(nonnull NSString *) listenerId) {
|
||||
[RNFirebaseFirestoreDocumentReference offSnapshot:listenerId];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(documentOnSnapshot:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(documentOnSnapshot:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
listenerId:(nonnull NSString *) listenerId
|
||||
docListenOptions:(NSDictionary *) docListenOptions) {
|
||||
RNFirebaseFirestoreDocumentReference *ref = [self getDocumentForAppPath:appName path:path];
|
||||
RNFirebaseFirestoreDocumentReference *ref = [self getDocumentForAppPath:appDisplayName path:path];
|
||||
[ref onSnapshot:listenerId docListenOptions:docListenOptions];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(documentSet:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(documentSet:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
data:(NSDictionary *) data
|
||||
options:(NSDictionary *) options
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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
|
||||
data:(NSDictionary *) data
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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);
|
||||
}
|
||||
|
||||
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appName {
|
||||
FIRApp *app = [FIRApp appNamed:appName];
|
||||
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appDisplayName {
|
||||
FIRApp *app = [RNFirebaseUtil getApp:appDisplayName];
|
||||
return [FIRFirestore firestoreForApp:app];
|
||||
}
|
||||
|
||||
- (RNFirebaseFirestoreCollectionReference *)getCollectionForAppPath:(NSString *)appName 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];
|
||||
- (RNFirebaseFirestoreCollectionReference *)getCollectionForAppPath:(NSString *)appDisplayName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options {
|
||||
return [[RNFirebaseFirestoreCollectionReference alloc] initWithPathAndModifiers:self appDisplayName:appDisplayName path:path filters:filters orders:orders options:options];
|
||||
}
|
||||
|
||||
- (RNFirebaseFirestoreDocumentReference *)getDocumentForAppPath:(NSString *)appName path:(NSString *)path {
|
||||
return [[RNFirebaseFirestoreDocumentReference alloc] initWithPath:self app:appName path:path];
|
||||
- (RNFirebaseFirestoreDocumentReference *)getDocumentForAppPath:(NSString *)appDisplayName path:(NSString *)path {
|
||||
return [[RNFirebaseFirestoreDocumentReference alloc] initWithPath:self appDisplayName:appDisplayName path:path];
|
||||
}
|
||||
|
||||
// TODO: Move to error util for use in other modules
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
|
||||
@interface RNFirebaseFirestoreCollectionReference : NSObject
|
||||
@property RCTEventEmitter *emitter;
|
||||
@property NSString *app;
|
||||
@property NSString *appDisplayName;
|
||||
@property NSString *path;
|
||||
@property NSArray *filters;
|
||||
@property NSArray *orders;
|
||||
@property NSDictionary *options;
|
||||
@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)offSnapshot:(NSString *)listenerId;
|
||||
- (void)onSnapshot:(NSString *)listenerId queryListenOptions:(NSDictionary *) queryListenOptions;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
static NSMutableDictionary *_listeners;
|
||||
|
||||
- (id)initWithPathAndModifiers:(RCTEventEmitter *) emitter
|
||||
app:(NSString *) app
|
||||
appDisplayName:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
filters:(NSArray *) filters
|
||||
orders:(NSArray *) orders
|
||||
|
@ -15,7 +15,7 @@ static NSMutableDictionary *_listeners;
|
|||
self = [super init];
|
||||
if (self) {
|
||||
_emitter = emitter;
|
||||
_app = app;
|
||||
_appDisplayName = appDisplayName;
|
||||
_path = path;
|
||||
_filters = filters;
|
||||
_orders = orders;
|
||||
|
@ -64,7 +64,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
|
|||
[self handleQuerySnapshotEvent:listenerId querySnapshot:snapshot];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FIRQueryListenOptions *options = [[FIRQueryListenOptions alloc] init];
|
||||
if (queryListenOptions) {
|
||||
if (queryListenOptions[@"includeDocumentMetadataChanges"]) {
|
||||
|
@ -74,14 +74,14 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
|
|||
[options includeQueryMetadataChanges:TRUE];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
id<FIRListenerRegistration> listener = [_query addSnapshotListenerWithOptions:options listener:listenerBlock];
|
||||
_listeners[listenerId] = listener;
|
||||
}
|
||||
}
|
||||
|
||||
- (FIRQuery *)buildQuery {
|
||||
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:_app];
|
||||
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:_appDisplayName];
|
||||
FIRQuery *query = (FIRQuery*)[firestore collectionWithPath:_path];
|
||||
query = [self applyFilters:firestore query:query];
|
||||
query = [self applyOrders:query];
|
||||
|
@ -152,7 +152,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
|
|||
- (void)handleQuerySnapshotError:(NSString *)listenerId
|
||||
error:(NSError *)error {
|
||||
NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
|
||||
[event setValue:_app forKey:@"appName"];
|
||||
[event setValue:_appDisplayName forKey:@"appName"];
|
||||
[event setValue:_path forKey:@"path"];
|
||||
[event setValue:listenerId forKey:@"listenerId"];
|
||||
[event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"];
|
||||
|
@ -163,7 +163,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
|
|||
- (void)handleQuerySnapshotEvent:(NSString *)listenerId
|
||||
querySnapshot:(FIRQuerySnapshot *)querySnapshot {
|
||||
NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
|
||||
[event setValue:_app forKey:@"appName"];
|
||||
[event setValue:_appDisplayName forKey:@"appName"];
|
||||
[event setValue:_path forKey:@"path"];
|
||||
[event setValue:listenerId forKey:@"listenerId"];
|
||||
[event setValue:[RNFirebaseFirestoreCollectionReference snapshotToDictionary:querySnapshot] forKey:@"querySnapshot"];
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
@interface RNFirebaseFirestoreDocumentReference : NSObject
|
||||
@property RCTEventEmitter *emitter;
|
||||
@property NSString *app;
|
||||
@property NSString *appDisplayName;
|
||||
@property NSString *path;
|
||||
@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)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
|
||||
+ (void)offSnapshot:(NSString *)listenerId;
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
static NSMutableDictionary *_listeners;
|
||||
|
||||
- (id)initWithPath:(RCTEventEmitter *)emitter
|
||||
app:(NSString *) app
|
||||
appDisplayName:(NSString *) appDisplayName
|
||||
path:(NSString *) path {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_emitter = emitter;
|
||||
_app = app;
|
||||
_appDisplayName = appDisplayName;
|
||||
_path = path;
|
||||
_ref = [[RNFirebaseFirestore getFirestoreForApp:_app] documentWithPath:_path];
|
||||
_ref = [[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] documentWithPath:_path];
|
||||
}
|
||||
// Initialise the static listeners object if required
|
||||
if (!_listeners) {
|
||||
|
@ -78,7 +78,7 @@ static NSMutableDictionary *_listeners;
|
|||
options:(NSDictionary *) options
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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"]) {
|
||||
[_ref setData:dictionary options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) {
|
||||
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
|
||||
|
@ -93,7 +93,7 @@ static NSMutableDictionary *_listeners;
|
|||
- (void)update:(NSDictionary *) data
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
|
||||
}];
|
||||
|
@ -131,7 +131,7 @@ static NSMutableDictionary *_listeners;
|
|||
- (void)handleDocumentSnapshotError:(NSString *)listenerId
|
||||
error:(NSError *)error {
|
||||
NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
|
||||
[event setValue:_app forKey:@"appName"];
|
||||
[event setValue:_appDisplayName forKey:@"appName"];
|
||||
[event setValue:_path forKey:@"path"];
|
||||
[event setValue:listenerId forKey:@"listenerId"];
|
||||
[event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"];
|
||||
|
@ -142,7 +142,7 @@ static NSMutableDictionary *_listeners;
|
|||
- (void)handleDocumentSnapshotEvent:(NSString *)listenerId
|
||||
documentSnapshot:(FIRDocumentSnapshot *)documentSnapshot {
|
||||
NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
|
||||
[event setValue:_app forKey:@"appName"];
|
||||
[event setValue:_appDisplayName forKey:@"appName"];
|
||||
[event setValue:_path forKey:@"path"];
|
||||
[event setValue:listenerId forKey:@"listenerId"];
|
||||
[event setValue:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:documentSnapshot] forKey:@"documentSnapshot"];
|
||||
|
|
|
@ -23,11 +23,11 @@ RCT_EXPORT_MODULE(RNFirebaseStorage);
|
|||
@url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete
|
||||
@param NSString path
|
||||
*/
|
||||
RCT_EXPORT_METHOD(delete:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(delete:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRStorageReference *fileRef = [self getReference:path appName:appName];
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
|
||||
[fileRef deleteWithCompletion:^(NSError *_Nullable error) {
|
||||
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
|
||||
@param NSString path
|
||||
*/
|
||||
RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
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
|
||||
@param NSString path
|
||||
*/
|
||||
RCT_EXPORT_METHOD(getMetadata:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(getMetadata:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
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) {
|
||||
if (error != nil) {
|
||||
|
@ -87,12 +87,12 @@ RCT_EXPORT_METHOD(getMetadata:(NSString *) appName
|
|||
@param NSString path
|
||||
@param NSDictionary metadata
|
||||
*/
|
||||
RCT_EXPORT_METHOD(updateMetadata:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(updateMetadata:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
metadata:(NSDictionary *) metadata
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRStorageReference *fileRef = [self getReference:path appName:appName];
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
|
||||
|
||||
[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 localPath
|
||||
*/
|
||||
RCT_EXPORT_METHOD(downloadFile:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(downloadFile:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
localPath:(NSString *) localPath
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRStorageReference *fileRef = [self getReference:path appName:appName];
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
NSURL *localFile = [NSURL fileURLWithPath:localPath];
|
||||
FIRStorageDownloadTask *downloadTask = [fileRef writeToFile:localFile];
|
||||
|
||||
|
@ -124,25 +124,25 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appName
|
|||
[downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
// download resumed, also fires when the upload starts
|
||||
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) {
|
||||
// download paused
|
||||
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) {
|
||||
// download reported progress
|
||||
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) {
|
||||
// download completed successfully
|
||||
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);
|
||||
}];
|
||||
|
||||
|
@ -161,9 +161,10 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appName
|
|||
@url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxDownloadRetryTime
|
||||
@param NSNumber milliseconds
|
||||
*/
|
||||
RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appDisplayName
|
||||
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
|
||||
@param NSNumber milliseconds
|
||||
*/
|
||||
RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appDisplayName
|
||||
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
|
||||
*/
|
||||
RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appDisplayName
|
||||
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 NSDictionary metadata
|
||||
*/
|
||||
RCT_EXPORT_METHOD(putFile:(NSString *) appName
|
||||
RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
path:(NSString *) path
|
||||
localPath:(NSString *) localPath
|
||||
metadata:(NSDictionary *) metadata
|
||||
|
@ -224,7 +227,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
|
|||
if (info[PHImageErrorKey] == nil) {
|
||||
if (UTTypeConformsTo((__bridge CFStringRef)dataUTI, kUTTypeJPEG)) {
|
||||
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 {
|
||||
// if the image UTI is not JPEG then convert to JPEG, e.g. HEI
|
||||
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
|
||||
|
@ -236,7 +239,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
|
|||
CGImageDestinationFinalize(destination);
|
||||
// Manually set mimetype to 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 {
|
||||
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:^{
|
||||
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
|
||||
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?
|
||||
} else {
|
||||
reject(@"storage/temporary-file-failure", @"Unable to create temporary file for upload.", nil);
|
||||
|
@ -274,7 +277,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
|
|||
} else {
|
||||
// TODO: Content type for file?
|
||||
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);
|
||||
}
|
||||
|
||||
- (void)uploadFile:(NSString *)appName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
||||
FIRStorageReference *fileRef = [self getReference:path appName:appName];
|
||||
- (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
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 {
|
||||
FIRStorageReference *fileRef = [self getReference:path appName:appName];
|
||||
- (void)uploadData:(NSString *)appDisplayName data:(NSData *)data firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
||||
FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName];
|
||||
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.
|
||||
[uploadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
|
||||
// upload resumed, also fires when the upload starts
|
||||
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) {
|
||||
// upload paused
|
||||
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) {
|
||||
// upload reported progress
|
||||
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) {
|
||||
// upload completed successfully
|
||||
NSDictionary *resp = [self getUploadTaskAsDictionary:snapshot];
|
||||
[self sendJSEvent:appName 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_STATE_CHANGED props:resp];
|
||||
[self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp];
|
||||
resolve(resp);
|
||||
}];
|
||||
|
||||
|
@ -335,12 +338,13 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName
|
|||
}
|
||||
|
||||
- (FIRStorageReference *)getReference:(NSString *)path
|
||||
appName:(NSString *)appName {
|
||||
appDisplayName:(NSString *)appDisplayName {
|
||||
FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName];
|
||||
if ([path hasPrefix:@"url::"]) {
|
||||
NSString *url = [path substringFromIndex:5];
|
||||
return [[FIRStorage storageForApp:[FIRApp appNamed:appName]] referenceForURL:url];
|
||||
return [[FIRStorage storageForApp:firApp] referenceForURL:url];
|
||||
} 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];
|
||||
}
|
||||
|
||||
- (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]};
|
||||
[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 {
|
||||
[RNFirebaseUtil sendJSEvent:self name:type body:@{@"eventName": title, @"appName": appName, @"path": path, @"body": 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": appDisplayName, @"path": path, @"body": props}];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,6 +64,10 @@ declare module "react-native-firebase" {
|
|||
*/
|
||||
crash(): RNFirebase.crash.Crash;
|
||||
|
||||
static fabric: {
|
||||
crashlytics(): RNFirebase.crashlytics.Crashlytics;
|
||||
};
|
||||
|
||||
apps: Array<string>;
|
||||
googleApiAvailability: RNFirebase.GoogleApiAvailabilityType;
|
||||
|
||||
|
@ -846,5 +850,50 @@ declare module "react-native-firebase" {
|
|||
[key: string]: any;
|
||||
}
|
||||
}
|
||||
|
||||
namespace crashlytics {
|
||||
|
||||
interface Crashlytics {
|
||||
/**
|
||||
* Forces a crash. Useful for testing your application is set up correctly.
|
||||
*/
|
||||
crash(): void;
|
||||
|
||||
/**
|
||||
* Logs a message that will appear in any subsequent crash reports.
|
||||
*/
|
||||
log(message: string): void;
|
||||
|
||||
/**
|
||||
* Logs a non fatal exception.
|
||||
*/
|
||||
recordError(code: number, message: string): void;
|
||||
|
||||
/**
|
||||
* Set a boolean value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setBoolValue(key: string, value: boolean): void;
|
||||
|
||||
/**
|
||||
* Set a float value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setFloatValue(key: string, value: number): void;
|
||||
|
||||
/**
|
||||
* Set an integer value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setIntValue(key: string, value: number): void;
|
||||
|
||||
/**
|
||||
* Set a string value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setStringValue(key: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Set the user ID to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setUserIdentifier(userId: string): void;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* @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;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { NativeModules, Platform } from 'react-native';
|
||||
import { statics } from './';
|
||||
import AdRequest from './AdRequest';
|
||||
import { SharedEventEmitter } from '../../utils/events';
|
||||
import { nativeToJSError } from '../../utils';
|
||||
|
||||
const FirebaseAdMob = NativeModules.RNFirebaseAdMob;
|
||||
|
@ -23,8 +24,8 @@ export default class Interstitial {
|
|||
this.admob = admob;
|
||||
this.adUnit = adUnit;
|
||||
this.loaded = false;
|
||||
this.admob.removeAllListeners(`interstitial_${adUnit}`);
|
||||
this.admob.on(`interstitial_${adUnit}`, this._onInterstitialEvent);
|
||||
SharedEventEmitter.removeAllListeners(`interstitial_${adUnit}`);
|
||||
SharedEventEmitter.addListener(`interstitial_${adUnit}`, this._onInterstitialEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,8 +49,8 @@ export default class Interstitial {
|
|||
default:
|
||||
}
|
||||
|
||||
this.admob.emit(eventType, emitData);
|
||||
this.admob.emit(`interstitial:${this.adUnit}:*`, emitData);
|
||||
SharedEventEmitter.emit(eventType, emitData);
|
||||
SharedEventEmitter.emit(`interstitial:${this.adUnit}:*`, emitData);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -97,7 +98,7 @@ export default class Interstitial {
|
|||
return null;
|
||||
}
|
||||
|
||||
const sub = this.admob.on(`interstitial:${this.adUnit}:${eventType}`, listenerCb);
|
||||
const sub = SharedEventEmitter.addListener(`interstitial:${this.adUnit}:${eventType}`, listenerCb);
|
||||
subscriptions.push(sub);
|
||||
return sub;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { NativeModules } from 'react-native';
|
||||
import { statics } from './';
|
||||
import AdRequest from './AdRequest';
|
||||
import { SharedEventEmitter } from '../../utils/events';
|
||||
import { nativeToJSError } from '../../utils';
|
||||
|
||||
const FirebaseAdMob = NativeModules.RNFirebaseAdMob;
|
||||
|
@ -18,8 +19,8 @@ export default class RewardedVideo {
|
|||
this.admob = admob;
|
||||
this.adUnit = adUnit;
|
||||
this.loaded = false;
|
||||
this.admob.removeAllListeners(`rewarded_video_${adUnit}`);
|
||||
this.admob.on(`rewarded_video_${adUnit}`, this._onRewardedVideoEvent);
|
||||
SharedEventEmitter.removeAllListeners(`rewarded_video_${adUnit}`);
|
||||
SharedEventEmitter.addListener(`rewarded_video_${adUnit}`, this._onRewardedVideoEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,8 +44,8 @@ export default class RewardedVideo {
|
|||
default:
|
||||
}
|
||||
|
||||
this.admob.emit(eventType, emitData);
|
||||
this.admob.emit(`rewarded_video:${this.adUnit}:*`, emitData);
|
||||
SharedEventEmitter.emit(eventType, emitData);
|
||||
SharedEventEmitter.emit(`rewarded_video:${this.adUnit}:*`, emitData);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -97,7 +98,7 @@ export default class RewardedVideo {
|
|||
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);
|
||||
return sub;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
* @flow
|
||||
* AdMob representation wrapper
|
||||
*/
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import { SharedEventEmitter } from '../../utils/events';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
|
||||
import Interstitial from './Interstitial';
|
||||
import RewardedVideo from './RewardedVideo';
|
||||
|
@ -16,7 +19,7 @@ import EventTypes, {
|
|||
RewardedVideoEventTypes,
|
||||
} from './EventTypes';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
type NativeEvent = {
|
||||
adUnit: string,
|
||||
|
@ -24,61 +27,70 @@ type NativeEvent = {
|
|||
type: string,
|
||||
}
|
||||
|
||||
export default class AdMob extends ModuleBase {
|
||||
static _NAMESPACE = 'admob';
|
||||
static _NATIVE_MODULE = 'RNFirebaseAdMob';
|
||||
const NATIVE_EVENTS = [
|
||||
'interstitial_event',
|
||||
'rewarded_video_event',
|
||||
];
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseAdmob';
|
||||
export const NAMESPACE = 'admob';
|
||||
|
||||
export default class AdMob extends ModuleBase {
|
||||
_appId: ?string;
|
||||
_initialized: boolean;
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options, true);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
events: NATIVE_EVENTS,
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
|
||||
this._initialized = false;
|
||||
this._appId = null;
|
||||
|
||||
this._eventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this));
|
||||
this._eventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this));
|
||||
SharedEventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this));
|
||||
SharedEventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this));
|
||||
}
|
||||
|
||||
_onInterstitialEvent(event: NativeEvent): void {
|
||||
const { adUnit } = event;
|
||||
const jsEventType = `interstitial_${adUnit}`;
|
||||
|
||||
if (!this.hasListeners(jsEventType)) {
|
||||
if (!SharedEventEmitter.hasListeners(jsEventType)) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
this.emit(jsEventType, event);
|
||||
SharedEventEmitter.emit(jsEventType, event);
|
||||
}
|
||||
|
||||
_onRewardedVideoEvent(event: NativeEvent): void {
|
||||
const { adUnit } = event;
|
||||
const jsEventType = `rewarded_video_${adUnit}`;
|
||||
|
||||
if (!this.hasListeners(jsEventType)) {
|
||||
if (!SharedEventEmitter.hasListeners(jsEventType)) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
this.emit(jsEventType, event);
|
||||
SharedEventEmitter.emit(jsEventType, event);
|
||||
}
|
||||
|
||||
initialize(appId: string): void {
|
||||
if (this._initialized) {
|
||||
this.log.warn('AdMob has already been initialized!');
|
||||
getLogger(this).warn('AdMob has already been initialized!');
|
||||
} else {
|
||||
this._initialized = true;
|
||||
this._appId = appId;
|
||||
this._native.initialize(appId);
|
||||
getNativeModule(this).initialize(appId);
|
||||
}
|
||||
}
|
||||
|
||||
openDebugMenu(): void {
|
||||
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 {
|
||||
this.log.info('Opening debug menu');
|
||||
this._native.openDebugMenu(this._appId);
|
||||
getLogger(this).info('Opening debug menu');
|
||||
getNativeModule(this).openDebugMenu(this._appId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +101,6 @@ export default class AdMob extends ModuleBase {
|
|||
rewarded(adUnit: string): RewardedVideo {
|
||||
return new RewardedVideo(this, adUnit);
|
||||
}
|
||||
|
||||
get namespace(): string {
|
||||
return 'firebase:admob';
|
||||
}
|
||||
}
|
||||
|
||||
export const statics = {
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
* @flow
|
||||
* Analytics representation wrapper
|
||||
*/
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
const AlphaNumericUnderscore = /^[a-zA-Z0-9_]+$/;
|
||||
|
||||
|
@ -24,12 +25,15 @@ const ReservedEventNames = [
|
|||
'user_engagement',
|
||||
];
|
||||
|
||||
export default class Analytics extends ModuleBase {
|
||||
static _NAMESPACE = 'analytics';
|
||||
static _NATIVE_MODULE = 'RNFirebaseAnalytics';
|
||||
export const MODULE_NAME = 'RNFirebaseAnalytics';
|
||||
export const NAMESPACE = 'analytics';
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options);
|
||||
export default class Analytics extends ModuleBase {
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,7 +61,7 @@ export default class Analytics extends ModuleBase {
|
|||
// types are supported. String parameter values can be up to 36 characters long. The "firebase_"
|
||||
// prefix is reserved and should not be used for parameter names.
|
||||
|
||||
this._native.logEvent(name, params);
|
||||
getNativeModule(this).logEvent(name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +69,7 @@ export default class Analytics extends ModuleBase {
|
|||
* @param enabled
|
||||
*/
|
||||
setAnalyticsCollectionEnabled(enabled: boolean): void {
|
||||
this._native.setAnalyticsCollectionEnabled(enabled);
|
||||
getNativeModule(this).setAnalyticsCollectionEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,7 +78,7 @@ export default class Analytics extends ModuleBase {
|
|||
* @param screenClassOverride
|
||||
*/
|
||||
setCurrentScreen(screenName: string, screenClassOverride: string): void {
|
||||
this._native.setCurrentScreen(screenName, screenClassOverride);
|
||||
getNativeModule(this).setCurrentScreen(screenName, screenClassOverride);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,7 +86,7 @@ export default class Analytics extends ModuleBase {
|
|||
* @param milliseconds
|
||||
*/
|
||||
setMinimumSessionDuration(milliseconds: number = 10000): void {
|
||||
this._native.setMinimumSessionDuration(milliseconds);
|
||||
getNativeModule(this).setMinimumSessionDuration(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,7 +94,7 @@ export default class Analytics extends ModuleBase {
|
|||
* @param milliseconds
|
||||
*/
|
||||
setSessionTimeoutDuration(milliseconds: number = 1800000): void {
|
||||
this._native.setSessionTimeoutDuration(milliseconds);
|
||||
getNativeModule(this).setSessionTimeoutDuration(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,7 +102,7 @@ export default class Analytics extends ModuleBase {
|
|||
* @param id
|
||||
*/
|
||||
setUserId(id: string): void {
|
||||
this._native.setUserId(id);
|
||||
getNativeModule(this).setUserId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,7 +111,7 @@ export default class Analytics extends ModuleBase {
|
|||
* @param value
|
||||
*/
|
||||
setUserProperty(name: string, value: string): void {
|
||||
this._native.setUserProperty(name, value);
|
||||
getNativeModule(this).setUserProperty(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,7 +121,7 @@ export default class Analytics extends ModuleBase {
|
|||
*/
|
||||
setUserProperties(object: Object): void {
|
||||
for (const property of Object.keys(object)) {
|
||||
this._native.setUserProperty(property, object[property]);
|
||||
getNativeModule(this).setUserProperty(property, object[property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* @flow
|
||||
* ConfirmationResult representation wrapper
|
||||
*/
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import type Auth from './';
|
||||
import type User from './User';
|
||||
|
||||
|
@ -25,7 +26,7 @@ export default class ConfirmationResult {
|
|||
* @return {*}
|
||||
*/
|
||||
confirm(verificationCode: string): Promise<?User> {
|
||||
return this._auth._interceptUserValue(this._auth._native._confirmVerificationCode(verificationCode));
|
||||
return this._auth._interceptUserValue(getNativeModule(this._auth)._confirmVerificationCode(verificationCode));
|
||||
}
|
||||
|
||||
get verificationId(): string | null {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// @flow
|
||||
import INTERNALS from '../../utils/internals';
|
||||
import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from './../../utils';
|
||||
import { SharedEventEmitter } from '../../utils/events';
|
||||
import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Auth from './';
|
||||
|
||||
|
@ -19,7 +21,7 @@ type PhoneAuthError = {
|
|||
};
|
||||
|
||||
export default class PhoneAuthListener {
|
||||
_auth: Object;
|
||||
_auth: Auth;
|
||||
_timeout: number;
|
||||
_publicEvents: Object;
|
||||
_internalEvents: Object;
|
||||
|
@ -68,7 +70,7 @@ export default class PhoneAuthListener {
|
|||
|
||||
// start verification flow natively
|
||||
if (isAndroid) {
|
||||
this._auth._native.verifyPhoneNumber(
|
||||
getNativeModule(this._auth).verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
this._phoneAuthRequestKey,
|
||||
this._timeout,
|
||||
|
@ -76,7 +78,7 @@ export default class PhoneAuthListener {
|
|||
}
|
||||
|
||||
if (isIOS) {
|
||||
this._auth._native.verifyPhoneNumber(
|
||||
getNativeModule(this._auth).verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
this._phoneAuthRequestKey,
|
||||
);
|
||||
|
@ -92,7 +94,8 @@ export default class PhoneAuthListener {
|
|||
|
||||
for (let i = 0, len = events.length; i < len; i++) {
|
||||
const type = events[i];
|
||||
this._auth.once(this._internalEvents[type], this[`_${type}Handler`].bind(this));
|
||||
// $FlowBug: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323
|
||||
SharedEventEmitter.once(this._internalEvents[type], this[`_${type}Handler`].bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +105,7 @@ export default class PhoneAuthListener {
|
|||
* @private
|
||||
*/
|
||||
_addUserObserver(observer) {
|
||||
this._auth.on(this._publicEvents.event, observer);
|
||||
SharedEventEmitter.addListener(this._publicEvents.event, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,7 +114,7 @@ export default class PhoneAuthListener {
|
|||
* @private
|
||||
*/
|
||||
_emitToObservers(snapshot: PhoneAuthSnapshot) {
|
||||
this._auth.emit(this._publicEvents.event, snapshot);
|
||||
SharedEventEmitter.emit(this._publicEvents.event, snapshot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,9 +123,9 @@ export default class PhoneAuthListener {
|
|||
* @private
|
||||
*/
|
||||
_emitToErrorCb(snapshot) {
|
||||
const error = snapshot.error;
|
||||
const { error } = snapshot;
|
||||
if (this._reject) this._reject(error);
|
||||
this._auth.emit(this._publicEvents.error, error);
|
||||
SharedEventEmitter.emit(this._publicEvents.error, error);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,7 +135,7 @@ export default class PhoneAuthListener {
|
|||
*/
|
||||
_emitToSuccessCb(snapshot) {
|
||||
if (this._resolve) this._resolve(snapshot);
|
||||
this._auth.emit(this._publicEvents.success, snapshot);
|
||||
SharedEventEmitter.emit(this._publicEvents.success, snapshot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -143,12 +146,12 @@ export default class PhoneAuthListener {
|
|||
setTimeout(() => { // move to next event loop - not sure if needed
|
||||
// internal listeners
|
||||
Object.values(this._internalEvents).forEach((event) => {
|
||||
this._auth.removeAllListeners(event);
|
||||
SharedEventEmitter.removeAllListeners(event);
|
||||
});
|
||||
|
||||
// user observer listeners
|
||||
Object.values(this._publicEvents).forEach((publicEvent) => {
|
||||
this._auth.removeAllListeners(publicEvent);
|
||||
SharedEventEmitter.removeAllListeners(publicEvent);
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
@ -279,11 +282,11 @@ export default class PhoneAuthListener {
|
|||
this._addUserObserver(observer);
|
||||
|
||||
if (isFunction(errorCb)) {
|
||||
this._auth.once(this._publicEvents.error, errorCb);
|
||||
SharedEventEmitter.once(this._publicEvents.error, errorCb);
|
||||
}
|
||||
|
||||
if (isFunction(successCb)) {
|
||||
this._auth.once(this._publicEvents.success, successCb);
|
||||
SharedEventEmitter.once(this._publicEvents.success, successCb);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -295,6 +298,7 @@ export default class PhoneAuthListener {
|
|||
*/
|
||||
then(fn: () => PhoneAuthSnapshot) {
|
||||
this._promiseDeferred();
|
||||
// $FlowFixMe: Unsure how to annotate `bind` here
|
||||
if (this._promise) return this._promise.then.bind(this._promise)(fn);
|
||||
return undefined; // will never get here - just to keep flow happy
|
||||
}
|
||||
|
@ -305,6 +309,7 @@ export default class PhoneAuthListener {
|
|||
*/
|
||||
catch(fn: () => Error) {
|
||||
this._promiseDeferred();
|
||||
// $FlowFixMe: Unsure how to annotate `bind` here
|
||||
if (this._promise) return this._promise.catch.bind(this._promise)(fn);
|
||||
return undefined; // will never get here - just to keep flow happy
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* User representation wrapper
|
||||
*/
|
||||
import INTERNALS from '../../utils/internals';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Auth from './';
|
||||
import type { ActionCodeSettings, AuthCredential } from '../../types';
|
||||
|
@ -92,7 +93,7 @@ export default class User {
|
|||
*/
|
||||
delete(): Promise<void> {
|
||||
return this._auth
|
||||
._interceptUndefinedUserValue(this._auth._native.delete());
|
||||
._interceptUndefinedUserValue(getNativeModule(this._auth).delete());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,7 +101,7 @@ export default class User {
|
|||
* @return {Promise}
|
||||
*/
|
||||
getIdToken(forceRefresh: boolean = false): Promise<string> {
|
||||
return this._auth._native.getToken(forceRefresh);
|
||||
return getNativeModule(this._auth).getToken(forceRefresh);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,7 +110,7 @@ export default class User {
|
|||
*/
|
||||
linkWithCredential(credential: AuthCredential): Promise<User> {
|
||||
return this._auth
|
||||
._interceptUserValue(this._auth._native.link(credential.providerId, credential.token, credential.secret));
|
||||
._interceptUserValue(getNativeModule(this._auth).link(credential.providerId, credential.token, credential.secret));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,7 +119,7 @@ export default class User {
|
|||
*/
|
||||
reauthenticateWithCredential(credential: AuthCredential): Promise<void> {
|
||||
return this._auth
|
||||
._interceptUndefinedUserValue(this._auth._native.reauthenticate(credential.providerId, credential.token, credential.secret));
|
||||
._interceptUndefinedUserValue(getNativeModule(this._auth).reauthenticate(credential.providerId, credential.token, credential.secret));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,7 +128,7 @@ export default class User {
|
|||
*/
|
||||
reload(): Promise<void> {
|
||||
return this._auth
|
||||
._interceptUndefinedUserValue(this._auth._native.reload());
|
||||
._interceptUndefinedUserValue(getNativeModule(this._auth).reload());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,7 +136,7 @@ export default class User {
|
|||
*/
|
||||
sendEmailVerification(actionCodeSettings?: ActionCodeSettings): Promise<void> {
|
||||
return this._auth
|
||||
._interceptUndefinedUserValue(this._auth._native.sendEmailVerification(actionCodeSettings));
|
||||
._interceptUndefinedUserValue(getNativeModule(this._auth).sendEmailVerification(actionCodeSettings));
|
||||
}
|
||||
|
||||
toJSON(): Object {
|
||||
|
@ -148,7 +149,7 @@ export default class User {
|
|||
* @return {Promise.<TResult>|*}
|
||||
*/
|
||||
unlink(providerId: string): Promise<User> {
|
||||
return this._auth._interceptUserValue(this._auth._native.unlink(providerId));
|
||||
return this._auth._interceptUserValue(getNativeModule(this._auth).unlink(providerId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +160,7 @@ export default class User {
|
|||
*/
|
||||
updateEmail(email: string): Promise<void> {
|
||||
return this._auth
|
||||
._interceptUndefinedUserValue(this._auth._native.updateEmail(email));
|
||||
._interceptUndefinedUserValue(getNativeModule(this._auth).updateEmail(email));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,7 +170,7 @@ export default class User {
|
|||
*/
|
||||
updatePassword(password: string): Promise<void> {
|
||||
return this._auth
|
||||
._interceptUndefinedUserValue(this._auth._native.updatePassword(password));
|
||||
._interceptUndefinedUserValue(getNativeModule(this._auth).updatePassword(password));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,7 +180,7 @@ export default class User {
|
|||
*/
|
||||
updateProfile(updates: Object = {}): Promise<void> {
|
||||
return this._auth
|
||||
._interceptUndefinedUserValue(this._auth._native.updateProfile(updates));
|
||||
._interceptUndefinedUserValue(getNativeModule(this._auth).updateProfile(updates));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,7 +190,7 @@ export default class User {
|
|||
*/
|
||||
getToken(forceRefresh: boolean = false): Promise<Object> {
|
||||
console.warn('Deprecated firebase.User.prototype.getToken in favor of firebase.User.prototype.getIdToken.');
|
||||
return this._auth._native.getToken(forceRefresh);
|
||||
return getNativeModule(this._auth).getToken(forceRefresh);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
*/
|
||||
import User from './User';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import INTERNALS from '../../utils/internals';
|
||||
import ConfirmationResult from './ConfirmationResult';
|
||||
|
||||
|
@ -18,48 +21,57 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider';
|
|||
import PhoneAuthListener from './PhoneAuthListener';
|
||||
|
||||
import type { ActionCodeSettings, AuthCredential } from '../../types';
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
type AuthResult = {
|
||||
authenticated: boolean,
|
||||
user: Object|null
|
||||
} | null;
|
||||
|
||||
export default class Auth extends ModuleBase {
|
||||
static _NAMESPACE = 'auth';
|
||||
static _NATIVE_MODULE = 'RNFirebaseAuth';
|
||||
const NATIVE_EVENTS = [
|
||||
'auth_state_changed',
|
||||
'phone_auth_state_changed',
|
||||
];
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseAuth';
|
||||
export const NAMESPACE = 'auth';
|
||||
|
||||
export default class Auth extends ModuleBase {
|
||||
_authResult: AuthResult | null;
|
||||
_user: User | null;
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options, true);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
events: NATIVE_EVENTS,
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
this._user = null;
|
||||
this._authResult = null;
|
||||
|
||||
this.addListener(
|
||||
SharedEventEmitter.addListener(
|
||||
// sub to internal native event - this fans out to
|
||||
// public event name: onAuthStateChanged
|
||||
super._getAppEventName('auth_state_changed'),
|
||||
getAppEventName(this, 'auth_state_changed'),
|
||||
this._onInternalAuthStateChanged.bind(this),
|
||||
);
|
||||
|
||||
this.addListener(
|
||||
SharedEventEmitter.addListener(
|
||||
// sub to internal native event - this fans out to
|
||||
// public events based on event.type
|
||||
super._getAppEventName('phone_auth_state_changed'),
|
||||
getAppEventName(this, 'phone_auth_state_changed'),
|
||||
this._onInternalPhoneAuthStateChanged.bind(this),
|
||||
);
|
||||
|
||||
this.addListener(
|
||||
SharedEventEmitter.addListener(
|
||||
// sub to internal native event - this fans out to
|
||||
// public event name: onIdTokenChanged
|
||||
super._getAppEventName('auth_id_token_changed'),
|
||||
getAppEventName(this, 'auth_id_token_changed'),
|
||||
this._onInternalIdTokenChanged.bind(this),
|
||||
);
|
||||
|
||||
this._native.addAuthStateListener();
|
||||
this._native.addIdTokenListener();
|
||||
getNativeModule(this).addAuthStateListener();
|
||||
getNativeModule(this).addIdTokenListener();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,13 +81,13 @@ export default class Auth extends ModuleBase {
|
|||
*/
|
||||
_onInternalPhoneAuthStateChanged(event: Object) {
|
||||
const eventKey = `phone:auth:${event.requestKey}:${event.type}`;
|
||||
this.emit(eventKey, event.state);
|
||||
SharedEventEmitter.emit(eventKey, event.state);
|
||||
}
|
||||
|
||||
_setAuthState(auth: AuthResult) {
|
||||
this._authResult = auth;
|
||||
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 +97,7 @@ export default class Auth extends ModuleBase {
|
|||
*/
|
||||
_onInternalAuthStateChanged(auth: AuthResult) {
|
||||
this._setAuthState(auth);
|
||||
this.emit(this._getAppEventName('onAuthStateChanged'), this._user);
|
||||
SharedEventEmitter.emit(getAppEventName(this, 'onAuthStateChanged'), this._user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +108,7 @@ export default class Auth extends ModuleBase {
|
|||
*/
|
||||
_onInternalIdTokenChanged(auth: AuthResult) {
|
||||
this._setAuthState(auth);
|
||||
this.emit(this._getAppEventName('onIdTokenChanged'), this._user);
|
||||
SharedEventEmitter.emit(getAppEventName(this, 'onIdTokenChanged'), this._user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,8 +141,8 @@ export default class Auth extends ModuleBase {
|
|||
* @param listener
|
||||
*/
|
||||
onAuthStateChanged(listener: Function) {
|
||||
this.log.info('Creating onAuthStateChanged listener');
|
||||
this.on(this._getAppEventName('onAuthStateChanged'), listener);
|
||||
getLogger(this).info('Creating onAuthStateChanged listener');
|
||||
SharedEventEmitter.addListener(getAppEventName(this, 'onAuthStateChanged'), listener);
|
||||
if (this._authResult) listener(this._user || null);
|
||||
return this._offAuthStateChanged.bind(this, listener);
|
||||
}
|
||||
|
@ -140,8 +152,8 @@ export default class Auth extends ModuleBase {
|
|||
* @param listener
|
||||
*/
|
||||
_offAuthStateChanged(listener: Function) {
|
||||
this.log.info('Removing onAuthStateChanged listener');
|
||||
this.removeListener(this._getAppEventName('onAuthStateChanged'), listener);
|
||||
getLogger(this).info('Removing onAuthStateChanged listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this, 'onAuthStateChanged'), listener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,8 +161,8 @@ export default class Auth extends ModuleBase {
|
|||
* @param listener
|
||||
*/
|
||||
onIdTokenChanged(listener: Function) {
|
||||
this.log.info('Creating onIdTokenChanged listener');
|
||||
this.on(this._getAppEventName('onIdTokenChanged'), listener);
|
||||
getLogger(this).info('Creating onIdTokenChanged listener');
|
||||
SharedEventEmitter.addListener(getAppEventName(this, 'onIdTokenChanged'), listener);
|
||||
if (this._authResult) listener(this._user || null);
|
||||
return this._offIdTokenChanged.bind(this, listener);
|
||||
}
|
||||
|
@ -160,8 +172,8 @@ export default class Auth extends ModuleBase {
|
|||
* @param listener
|
||||
*/
|
||||
_offIdTokenChanged(listener: Function) {
|
||||
this.log.info('Removing onIdTokenChanged listener');
|
||||
this.removeListener(this._getAppEventName('onIdTokenChanged'), listener);
|
||||
getLogger(this).info('Removing onIdTokenChanged listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this, 'onIdTokenChanged'), listener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,8 +181,8 @@ export default class Auth extends ModuleBase {
|
|||
* @param listener
|
||||
*/
|
||||
onUserChanged(listener: Function) {
|
||||
this.log.info('Creating onUserChanged listener');
|
||||
this.on(this._getAppEventName('onUserChanged'), listener);
|
||||
getLogger(this).info('Creating onUserChanged listener');
|
||||
SharedEventEmitter.addListener(getAppEventName(this, 'onUserChanged'), listener);
|
||||
if (this._authResult) listener(this._user || null);
|
||||
return this._offUserChanged.bind(this, listener);
|
||||
}
|
||||
|
@ -180,8 +192,8 @@ export default class Auth extends ModuleBase {
|
|||
* @param listener
|
||||
*/
|
||||
_offUserChanged(listener: Function) {
|
||||
this.log.info('Removing onUserChanged listener');
|
||||
this.removeListener(this._getAppEventName('onUserChanged'), listener);
|
||||
getLogger(this).info('Removing onUserChanged listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this, 'onUserChanged'), listener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,7 +201,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise}
|
||||
*/
|
||||
signOut(): Promise<void> {
|
||||
return this._interceptUndefinedUserValue(this._native.signOut());
|
||||
return this._interceptUndefinedUserValue(getNativeModule(this).signOut());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,7 +209,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInAnonymously(): Promise<User> {
|
||||
return this._interceptUserValue(this._native.signInAnonymously());
|
||||
return this._interceptUserValue(getNativeModule(this).signInAnonymously());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +219,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise} A promise indicating the completion
|
||||
*/
|
||||
createUserWithEmailAndPassword(email: string, password: string): Promise<User> {
|
||||
return this._interceptUserValue(this._native.createUserWithEmailAndPassword(email, password));
|
||||
return this._interceptUserValue(getNativeModule(this).createUserWithEmailAndPassword(email, password));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -217,7 +229,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise} A promise that is resolved upon completion
|
||||
*/
|
||||
signInWithEmailAndPassword(email: string, password: string): Promise<User> {
|
||||
return this._interceptUserValue(this._native.signInWithEmailAndPassword(email, password));
|
||||
return this._interceptUserValue(getNativeModule(this).signInWithEmailAndPassword(email, password));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -226,7 +238,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInWithCustomToken(customToken: string): Promise<User> {
|
||||
return this._interceptUserValue(this._native.signInWithCustomToken(customToken));
|
||||
return this._interceptUserValue(getNativeModule(this).signInWithCustomToken(customToken));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,7 +247,7 @@ export default class Auth extends ModuleBase {
|
|||
*/
|
||||
signInWithCredential(credential: AuthCredential): Promise<User> {
|
||||
return this._interceptUserValue(
|
||||
this._native.signInWithCredential(
|
||||
getNativeModule(this).signInWithCredential(
|
||||
credential.providerId, credential.token, credential.secret,
|
||||
),
|
||||
);
|
||||
|
@ -246,7 +258,7 @@ export default class Auth extends ModuleBase {
|
|||
*
|
||||
*/
|
||||
signInWithPhoneNumber(phoneNumber: string): Promise<ConfirmationResult> {
|
||||
return this._native.signInWithPhoneNumber(phoneNumber).then((result) => {
|
||||
return getNativeModule(this).signInWithPhoneNumber(phoneNumber).then((result) => {
|
||||
return new ConfirmationResult(this, result.verificationId);
|
||||
});
|
||||
}
|
||||
|
@ -269,7 +281,7 @@ export default class Auth extends ModuleBase {
|
|||
* @param {string} email The email to send password reset instructions
|
||||
*/
|
||||
sendPasswordResetEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise<void> {
|
||||
return this._native.sendPasswordResetEmail(email, actionCodeSettings);
|
||||
return getNativeModule(this).sendPasswordResetEmail(email, actionCodeSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,7 +293,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise.<Null>}
|
||||
*/
|
||||
confirmPasswordReset(code: string, newPassword: string): Promise<void> {
|
||||
return this._native.confirmPasswordReset(code, newPassword);
|
||||
return getNativeModule(this).confirmPasswordReset(code, newPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -292,7 +304,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise.<Null>}
|
||||
*/
|
||||
applyActionCode(code: string): Promise<void> {
|
||||
return this._native.applyActionCode(code);
|
||||
return getNativeModule(this).applyActionCode(code);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -303,7 +315,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise.<any>|Promise<ActionCodeInfo>}
|
||||
*/
|
||||
checkActionCode(code: string): Promise<void> {
|
||||
return this._native.checkActionCode(code);
|
||||
return getNativeModule(this).checkActionCode(code);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -311,7 +323,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise}
|
||||
*/
|
||||
getCurrentUser(): Promise<User | null> {
|
||||
return this._interceptUserValue(this._native.getCurrentUser());
|
||||
return this._interceptUserValue(getNativeModule(this).getCurrentUser());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -319,7 +331,7 @@ export default class Auth extends ModuleBase {
|
|||
* @return {Promise}
|
||||
*/
|
||||
fetchProvidersForEmail(email: string): Promise<Array<String>> {
|
||||
return this._native.fetchProvidersForEmail(email);
|
||||
return getNativeModule(this).fetchProvidersForEmail(email);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -330,32 +342,28 @@ export default class Auth extends ModuleBase {
|
|||
return this._user;
|
||||
}
|
||||
|
||||
get namespace(): string {
|
||||
return 'firebase:auth';
|
||||
}
|
||||
|
||||
/**
|
||||
* KNOWN UNSUPPORTED METHODS
|
||||
*/
|
||||
|
||||
getRedirectResult() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'getRedirectResult'));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'getRedirectResult'));
|
||||
}
|
||||
|
||||
setPersistence() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'setPersistence'));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'setPersistence'));
|
||||
}
|
||||
|
||||
signInAndRetrieveDataWithCredential() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInAndRetrieveDataWithCredential'));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInAndRetrieveDataWithCredential'));
|
||||
}
|
||||
|
||||
signInWithPopup() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInWithPopup'));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInWithPopup'));
|
||||
}
|
||||
|
||||
signInWithRedirect() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInWithRedirect'));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInWithRedirect'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
* @flow
|
||||
* Remote Config representation wrapper
|
||||
*/
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
type NativeValue = {
|
||||
stringValue?: string,
|
||||
|
@ -14,17 +16,20 @@ type NativeValue = {
|
|||
source: 'remoteConfigSourceRemote' | 'remoteConfigSourceDefault' | ' remoteConfigSourceStatic',
|
||||
}
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseRemoteConfig';
|
||||
export const NAMESPACE = 'config';
|
||||
|
||||
/**
|
||||
* @class Config
|
||||
*/
|
||||
export default class RemoteConfig extends ModuleBase {
|
||||
static _NAMESPACE = 'config';
|
||||
static _NATIVE_MODULE = 'RNFirebaseRemoteConfig';
|
||||
|
||||
_developerModeEnabled: boolean;
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
this._developerModeEnabled = false;
|
||||
}
|
||||
|
||||
|
@ -39,7 +44,7 @@ export default class RemoteConfig extends ModuleBase {
|
|||
source: nativeValue.source,
|
||||
val() {
|
||||
if (nativeValue.boolValue !== null && (nativeValue.stringValue === 'true' || nativeValue.stringValue === 'false' || nativeValue.stringValue === null)) return nativeValue.boolValue;
|
||||
if (nativeValue.numberValue !== null && (nativeValue.stringValue == null || nativeValue.stringValue === '' || `${nativeValue.numberValue}` === nativeValue.stringValue)) return nativeValue.numberValue;
|
||||
if (nativeValue.numberValue !== null && nativeValue.numberValue !== undefined && (nativeValue.stringValue == null || nativeValue.stringValue === '' || nativeValue.numberValue.toString() === nativeValue.stringValue)) return nativeValue.numberValue;
|
||||
if (nativeValue.dataValue !== nativeValue.stringValue && (nativeValue.stringValue == null || nativeValue.stringValue === '')) return nativeValue.dataValue;
|
||||
return nativeValue.stringValue;
|
||||
},
|
||||
|
@ -51,8 +56,8 @@ export default class RemoteConfig extends ModuleBase {
|
|||
*/
|
||||
enableDeveloperMode() {
|
||||
if (!this._developerModeEnabled) {
|
||||
this.log.debug('Enabled developer mode');
|
||||
this._native.enableDeveloperMode();
|
||||
getLogger(this).debug('Enabled developer mode');
|
||||
getNativeModule(this).enableDeveloperMode();
|
||||
this._developerModeEnabled = true;
|
||||
}
|
||||
}
|
||||
|
@ -64,11 +69,11 @@ export default class RemoteConfig extends ModuleBase {
|
|||
*/
|
||||
fetch(expiration?: number) {
|
||||
if (expiration !== undefined) {
|
||||
this.log.debug(`Fetching remote config data with expiration ${expiration.toString()}`);
|
||||
return this._native.fetchWithExpirationDuration(expiration);
|
||||
getLogger(this).debug(`Fetching remote config data with expiration ${expiration.toString()}`);
|
||||
return getNativeModule(this).fetchWithExpirationDuration(expiration);
|
||||
}
|
||||
this.log.debug('Fetching remote config data');
|
||||
return this._native.fetch();
|
||||
getLogger(this).debug('Fetching remote config data');
|
||||
return getNativeModule(this).fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,8 +83,8 @@ export default class RemoteConfig extends ModuleBase {
|
|||
* rejects if no Fetched Config was found, or the Fetched Config was already activated.
|
||||
*/
|
||||
activateFetched() {
|
||||
this.log.debug('Activating remote config');
|
||||
return this._native.activateFetched();
|
||||
getLogger(this).debug('Activating remote config');
|
||||
return getNativeModule(this).activateFetched();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +101,7 @@ export default class RemoteConfig extends ModuleBase {
|
|||
* }
|
||||
*/
|
||||
getValue(key: String) {
|
||||
return this._native
|
||||
return getNativeModule(this)
|
||||
.getValue(key || '')
|
||||
.then(this._nativeValueToJS);
|
||||
}
|
||||
|
@ -116,7 +121,7 @@ export default class RemoteConfig extends ModuleBase {
|
|||
* }
|
||||
*/
|
||||
getValues(keys: Array<String>) {
|
||||
return this._native
|
||||
return getNativeModule(this)
|
||||
.getValues(keys || [])
|
||||
.then((nativeValues) => {
|
||||
const values: { [String]: Object } = {};
|
||||
|
@ -133,7 +138,7 @@ export default class RemoteConfig extends ModuleBase {
|
|||
* @returns {*|Promise.<Array<String>>}
|
||||
*/
|
||||
getKeysByPrefix(prefix?: String) {
|
||||
return this._native.getKeysByPrefix(prefix);
|
||||
return getNativeModule(this).getKeysByPrefix(prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,7 +146,7 @@ export default class RemoteConfig extends ModuleBase {
|
|||
* @param defaults: A dictionary mapping a String key to a Object values.
|
||||
*/
|
||||
setDefaults(defaults: Object) {
|
||||
this._native.setDefaults(defaults);
|
||||
getNativeModule(this).setDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,7 +154,7 @@ export default class RemoteConfig extends ModuleBase {
|
|||
* @param resource: The plist file name or resource ID
|
||||
*/
|
||||
setDefaultsFromResource(resource: String | number) {
|
||||
this._native.setDefaultsFromResource(resource);
|
||||
getNativeModule(this).setDefaultsFromResource(resource);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,112 +3,85 @@
|
|||
*/
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import APPS from '../../utils/apps';
|
||||
import { SharedEventEmitter } from '../../utils/events';
|
||||
import INTERNALS from '../../utils/internals';
|
||||
import { isObject, isAndroid } from '../../utils';
|
||||
import { isObject } from '../../utils';
|
||||
|
||||
import AdMob, { statics as AdMobStatics } from '../admob';
|
||||
import Auth, { statics as AuthStatics } from '../auth';
|
||||
import Analytics, { statics as AnalyticsStatics } from '../analytics';
|
||||
import Config, { statics as ConfigStatics } from '../config';
|
||||
import Crash, { statics as CrashStatics } from '../crash';
|
||||
import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics';
|
||||
import Database, { statics as DatabaseStatics } from '../database';
|
||||
import Firestore, { statics as FirestoreStatics } from '../firestore';
|
||||
import Links, { statics as LinksStatics } from '../links';
|
||||
import Messaging, { statics as MessagingStatics } from '../messaging';
|
||||
import Performance, { statics as PerformanceStatics } from '../perf';
|
||||
import Storage, { statics as StorageStatics } from '../storage';
|
||||
import Utils, { statics as UtilsStatics } from '../utils';
|
||||
import AdMob, { NAMESPACE as AdmobNamespace } from '../admob';
|
||||
import Auth, { NAMESPACE as AuthNamespace } from '../auth';
|
||||
import Analytics, { NAMESPACE as AnalyticsNamespace } from '../analytics';
|
||||
import Config, { NAMESPACE as ConfigNamespace } from '../config';
|
||||
import Crash, { NAMESPACE as CrashNamespace } from '../crash';
|
||||
import Crashlytics, { NAMESPACE as CrashlyticsNamespace } from '../fabric/crashlytics';
|
||||
import Database, { NAMESPACE as DatabaseNamespace } from '../database';
|
||||
import Firestore, { NAMESPACE as FirestoreNamespace } from '../firestore';
|
||||
import Links, { NAMESPACE as LinksNamespace } from '../links';
|
||||
import Messaging, { NAMESPACE as MessagingNamespace } from '../messaging';
|
||||
import Performance, { NAMESPACE as PerfNamespace } from '../perf';
|
||||
import Storage, { NAMESPACE as StorageNamespace } from '../storage';
|
||||
import Utils, { NAMESPACE as UtilsNamespace } from '../utils';
|
||||
|
||||
import type {
|
||||
AdMobModule,
|
||||
AnalyticsModule,
|
||||
AuthModule,
|
||||
ConfigModule,
|
||||
CrashModule,
|
||||
DatabaseModule,
|
||||
FabricModule,
|
||||
FirebaseModule,
|
||||
FirebaseModuleAndStatics,
|
||||
FirebaseOptions,
|
||||
FirebaseStatics,
|
||||
FirestoreModule,
|
||||
LinksModule,
|
||||
MessagingModule,
|
||||
PerformanceModule,
|
||||
StorageModule,
|
||||
UtilsModule,
|
||||
} from '../../types';
|
||||
|
||||
const FirebaseCoreModule = NativeModules.RNFirebase;
|
||||
|
||||
|
||||
export default class FirebaseApp {
|
||||
export default class App {
|
||||
_extendedProps: { [string] : boolean };
|
||||
_initialized: boolean;
|
||||
_initialized: boolean = false;
|
||||
_name: string;
|
||||
_namespaces: { [string]: FirebaseModule };
|
||||
_nativeInitialized: boolean;
|
||||
_nativeInitialized: boolean = false;
|
||||
_options: FirebaseOptions;
|
||||
admob: AdMobModule;
|
||||
analytics: AnalyticsModule;
|
||||
auth: AuthModule;
|
||||
config: ConfigModule;
|
||||
crash: CrashModule;
|
||||
database: DatabaseModule;
|
||||
fabric: FabricModule;
|
||||
firestore: FirestoreModule;
|
||||
links: LinksModule;
|
||||
messaging: MessagingModule;
|
||||
perf: PerformanceModule;
|
||||
storage: StorageModule;
|
||||
utils: UtilsModule;
|
||||
admob: () => AdMob;
|
||||
analytics: () => Analytics;
|
||||
auth: () => Auth;
|
||||
config: () => Config;
|
||||
crash: () => Crash;
|
||||
database: () => Database;
|
||||
fabric: {
|
||||
crashlytics: () => Crashlytics,
|
||||
};
|
||||
firestore: () => Firestore;
|
||||
links: () => Links;
|
||||
messaging: () => Messaging;
|
||||
perf: () => Performance;
|
||||
storage: () => Storage;
|
||||
utils: () => Utils;
|
||||
|
||||
constructor(name: string, options: FirebaseOptions) {
|
||||
constructor(name: string, options: FirebaseOptions, fromNative: boolean = false) {
|
||||
this._name = name;
|
||||
this._namespaces = {};
|
||||
this._options = Object.assign({}, options);
|
||||
|
||||
// native ios/android to confirm initialized
|
||||
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
|
||||
if (fromNative) {
|
||||
this._initialized = true;
|
||||
this._nativeInitialized = true;
|
||||
} else {
|
||||
} else if (options.databaseURL && options.apiKey) {
|
||||
FirebaseCoreModule.initializeApp(this._name, this._options, (error, result) => {
|
||||
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 {*}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -153,6 +119,7 @@ export default class FirebaseApp {
|
|||
throw new Error(INTERNALS.STRINGS.ERROR_PROTECTED_PROP(key));
|
||||
}
|
||||
|
||||
// $FlowBug: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323
|
||||
this[key] = props[key];
|
||||
this._extendedProps[key] = true;
|
||||
}
|
||||
|
@ -165,7 +132,7 @@ export default class FirebaseApp {
|
|||
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
|
||||
// if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME && this._nativeInitialized) {
|
||||
// if (this._name === APPS.DEFAULT_APP_NAME && this._nativeInitialized) {
|
||||
// return Promise.reject(
|
||||
// new Error('Unable to delete the default native firebase app instance.'),
|
||||
// );
|
||||
|
@ -179,42 +146,14 @@ export default class FirebaseApp {
|
|||
*
|
||||
* @return {*}
|
||||
*/
|
||||
onReady(): Promise<FirebaseApp> {
|
||||
onReady(): Promise<App> {
|
||||
if (this._initialized) return Promise.resolve(this);
|
||||
|
||||
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
|
||||
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],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,26 +2,26 @@
|
|||
* @providesModule Firebase
|
||||
* @flow
|
||||
*/
|
||||
import { NativeModules, NativeEventEmitter } from 'react-native';
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import APPS from '../../utils/apps';
|
||||
import INTERNALS from '../../utils/internals';
|
||||
import FirebaseApp from './firebase-app';
|
||||
import { isObject, isString } from '../../utils';
|
||||
import App from './firebase-app';
|
||||
|
||||
// module imports
|
||||
import AdMob, { statics as AdMobStatics } from '../admob';
|
||||
import Auth, { statics as AuthStatics } from '../auth';
|
||||
import Analytics, { statics as AnalyticsStatics } from '../analytics';
|
||||
import Config, { statics as ConfigStatics } from '../config';
|
||||
import Crash, { statics as CrashStatics } from '../crash';
|
||||
import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics';
|
||||
import Database, { statics as DatabaseStatics } from '../database';
|
||||
import Firestore, { statics as FirestoreStatics } from '../firestore';
|
||||
import Links, { statics as LinksStatics } from '../links';
|
||||
import Messaging, { statics as MessagingStatics } from '../messaging';
|
||||
import Performance, { statics as PerformanceStatics } from '../perf';
|
||||
import Storage, { statics as StorageStatics } from '../storage';
|
||||
import Utils, { statics as UtilsStatics } from '../utils';
|
||||
import { statics as AdMobStatics, MODULE_NAME as AdmobModuleName } from '../admob';
|
||||
import { statics as AuthStatics, MODULE_NAME as AuthModuleName } from '../auth';
|
||||
import { statics as AnalyticsStatics, MODULE_NAME as AnalyticsModuleName } from '../analytics';
|
||||
import { statics as ConfigStatics, MODULE_NAME as ConfigModuleName } from '../config';
|
||||
import { statics as CrashStatics, MODULE_NAME as CrashModuleName } from '../crash';
|
||||
import { statics as CrashlyticsStatics, MODULE_NAME as CrashlyticsModuleName } from '../fabric/crashlytics';
|
||||
import { statics as DatabaseStatics, MODULE_NAME as DatabaseModuleName } from '../database';
|
||||
import { statics as FirestoreStatics, MODULE_NAME as FirestoreModuleName } from '../firestore';
|
||||
import { statics as LinksStatics, MODULE_NAME as LinksModuleName } from '../links';
|
||||
import { statics as MessagingStatics, MODULE_NAME as MessagingModuleName } from '../messaging';
|
||||
import { statics as PerformanceStatics, MODULE_NAME as PerfModuleName } from '../perf';
|
||||
import { statics as StorageStatics, MODULE_NAME as StorageModuleName } from '../storage';
|
||||
import { statics as UtilsStatics, MODULE_NAME as UtilsModuleName } from '../utils';
|
||||
|
||||
import type {
|
||||
AdMobModule,
|
||||
|
@ -31,10 +31,7 @@ import type {
|
|||
CrashModule,
|
||||
DatabaseModule,
|
||||
FabricModule,
|
||||
FirebaseModule,
|
||||
FirebaseModuleAndStatics,
|
||||
FirebaseOptions,
|
||||
FirebaseStatics,
|
||||
FirestoreModule,
|
||||
LinksModule,
|
||||
MessagingModule,
|
||||
|
@ -45,9 +42,7 @@ import type {
|
|||
|
||||
const FirebaseCoreModule = NativeModules.RNFirebase;
|
||||
|
||||
class FirebaseCore {
|
||||
_nativeEmitters: { [string]: NativeEventEmitter };
|
||||
_nativeSubscriptions: { [string]: boolean };
|
||||
class Firebase {
|
||||
admob: AdMobModule;
|
||||
analytics: AnalyticsModule;
|
||||
auth: AuthModule;
|
||||
|
@ -63,45 +58,27 @@ class FirebaseCore {
|
|||
utils: UtilsModule;
|
||||
|
||||
constructor() {
|
||||
this._nativeEmitters = {};
|
||||
this._nativeSubscriptions = {};
|
||||
|
||||
if (!FirebaseCoreModule) {
|
||||
throw (new Error(INTERNALS.STRINGS.ERROR_MISSING_CORE));
|
||||
}
|
||||
|
||||
this._initializeNativeApps();
|
||||
APPS.initializeNativeApps();
|
||||
|
||||
// modules
|
||||
this.admob = this._appNamespaceOrStatics(AdMobStatics, AdMob);
|
||||
this.analytics = this._appNamespaceOrStatics(AnalyticsStatics, Analytics);
|
||||
this.auth = this._appNamespaceOrStatics(AuthStatics, Auth);
|
||||
this.config = this._appNamespaceOrStatics(ConfigStatics, Config);
|
||||
this.crash = this._appNamespaceOrStatics(CrashStatics, Crash);
|
||||
this.database = this._appNamespaceOrStatics(DatabaseStatics, Database);
|
||||
this.admob = APPS.moduleAndStatics('admob', AdMobStatics, AdmobModuleName);
|
||||
this.analytics = APPS.moduleAndStatics('analytics', AnalyticsStatics, AnalyticsModuleName);
|
||||
this.auth = APPS.moduleAndStatics('auth', AuthStatics, AuthModuleName);
|
||||
this.config = APPS.moduleAndStatics('config', ConfigStatics, ConfigModuleName);
|
||||
this.crash = APPS.moduleAndStatics('crash', CrashStatics, CrashModuleName);
|
||||
this.database = APPS.moduleAndStatics('database', DatabaseStatics, DatabaseModuleName);
|
||||
this.fabric = {
|
||||
crashlytics: this._appNamespaceOrStatics(CrashlyticsStatics, Crashlytics),
|
||||
crashlytics: APPS.moduleAndStatics('crashlytics', CrashlyticsStatics, CrashlyticsModuleName),
|
||||
};
|
||||
this.firestore = this._appNamespaceOrStatics(FirestoreStatics, Firestore);
|
||||
this.links = this._appNamespaceOrStatics(LinksStatics, Links);
|
||||
this.messaging = this._appNamespaceOrStatics(MessagingStatics, Messaging);
|
||||
this.perf = this._appNamespaceOrStatics(PerformanceStatics, Performance);
|
||||
this.storage = this._appNamespaceOrStatics(StorageStatics, Storage);
|
||||
this.utils = this._appNamespaceOrStatics(UtilsStatics, Utils);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
this.firestore = APPS.moduleAndStatics('firestore', FirestoreStatics, FirestoreModuleName);
|
||||
this.links = APPS.moduleAndStatics('links', LinksStatics, LinksModuleName);
|
||||
this.messaging = APPS.moduleAndStatics('messaging', MessagingStatics, MessagingModuleName);
|
||||
this.perf = APPS.moduleAndStatics('perf', PerformanceStatics, PerfModuleName);
|
||||
this.storage = APPS.moduleAndStatics('storage', StorageStatics, StorageModuleName);
|
||||
this.utils = APPS.moduleAndStatics('utils', UtilsStatics, UtilsModuleName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,58 +88,8 @@ class FirebaseCore {
|
|||
* @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 || 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];
|
||||
initializeApp(options: FirebaseOptions, name: string): App {
|
||||
return APPS.initializeApp(options, name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,96 +101,17 @@ class FirebaseCore {
|
|||
* @param name
|
||||
* @return {*}
|
||||
*/
|
||||
app(name?: string): FirebaseApp {
|
||||
const _name = name ? name.toUpperCase() : INTERNALS.STRINGS.DEFAULT_APP_NAME;
|
||||
const app = INTERNALS.APPS[_name];
|
||||
if (!app) throw new Error(INTERNALS.STRINGS.ERROR_APP_NOT_INIT(_name));
|
||||
return app;
|
||||
app(name?: string): App {
|
||||
return APPS.app(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* A (read-only) array of all initialized apps.
|
||||
* @return {Array}
|
||||
*/
|
||||
get apps(): Array<FirebaseApp> {
|
||||
return Object.values(INTERNALS.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);
|
||||
get apps(): Array<App> {
|
||||
return APPS.apps();
|
||||
}
|
||||
}
|
||||
|
||||
export default new FirebaseCore();
|
||||
export default new Firebase();
|
||||
|
|
|
@ -3,16 +3,20 @@
|
|||
* Crash Reporting representation wrapper
|
||||
*/
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
import type { FirebaseError } from '../../types';
|
||||
|
||||
export default class Crash extends ModuleBase {
|
||||
static _NAMESPACE = 'crash';
|
||||
static _NATIVE_MODULE = 'RNFirebaseCrash';
|
||||
export const MODULE_NAME = 'RNFirebaseCrash';
|
||||
export const NAMESPACE = 'crash';
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options);
|
||||
export default class Crash extends ModuleBase {
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,7 +24,7 @@ export default class Crash extends ModuleBase {
|
|||
* @param enabled
|
||||
*/
|
||||
setCrashCollectionEnabled(enabled: boolean): void {
|
||||
this._native.setCrashCollectionEnabled(enabled);
|
||||
getNativeModule(this).setCrashCollectionEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,7 +32,7 @@ export default class Crash extends ModuleBase {
|
|||
* @returns {Promise.<boolean>}
|
||||
*/
|
||||
isCrashCollectionEnabled(): Promise<boolean> {
|
||||
return this._native.isCrashCollectionEnabled();
|
||||
return getNativeModule(this).isCrashCollectionEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,7 +40,7 @@ export default class Crash extends ModuleBase {
|
|||
* @param {string} message
|
||||
*/
|
||||
log(message: string): void {
|
||||
this._native.log(message);
|
||||
getNativeModule(this).log(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,7 +51,7 @@ export default class Crash extends ModuleBase {
|
|||
* @param {string} tag
|
||||
*/
|
||||
logcat(level: number, tag: string, message: string): void {
|
||||
this._native.logcat(level, tag, message);
|
||||
getNativeModule(this).logcat(level, tag, message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,7 +78,7 @@ export default class Crash extends ModuleBase {
|
|||
errorMessage = `${errorMessage} - ${stackRows[i]}\r\n`;
|
||||
}
|
||||
|
||||
this._native.report(errorMessage);
|
||||
getNativeModule(this).report(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
* @flow
|
||||
* Disconnect representation wrapper
|
||||
*/
|
||||
import { typeOf } from './../../utils';
|
||||
import { typeOf } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import type Database from './';
|
||||
import type Reference from './reference';
|
||||
|
||||
|
@ -32,7 +33,7 @@ export default class Disconnect {
|
|||
* @returns {*}
|
||||
*/
|
||||
set(value: string | Object): Promise<void> {
|
||||
return this._database._native.onDisconnectSet(this.path, { type: typeOf(value), value });
|
||||
return getNativeModule(this._database).onDisconnectSet(this.path, { type: typeOf(value), value });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +42,7 @@ export default class Disconnect {
|
|||
* @returns {*}
|
||||
*/
|
||||
update(values: Object): Promise<void> {
|
||||
return this._database._native.onDisconnectUpdate(this.path, values);
|
||||
return getNativeModule(this._database).onDisconnectUpdate(this.path, values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,7 +50,7 @@ export default class Disconnect {
|
|||
* @returns {*}
|
||||
*/
|
||||
remove(): Promise<void> {
|
||||
return this._database._native.onDisconnectRemove(this.path);
|
||||
return getNativeModule(this._database).onDisconnectRemove(this.path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,6 +58,6 @@ export default class Disconnect {
|
|||
* @returns {*}
|
||||
*/
|
||||
cancel(): Promise<void> {
|
||||
return this._database._native.onDisconnectCancel(this.path);
|
||||
return getNativeModule(this._database).onDisconnectCancel(this.path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,27 +6,37 @@ import { NativeModules } from 'react-native';
|
|||
|
||||
import Reference from './reference';
|
||||
import TransactionHandler from './transaction';
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App 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
|
||||
*/
|
||||
export default class Database extends ModuleBase {
|
||||
static _NAMESPACE = 'database';
|
||||
static _NATIVE_MODULE = 'RNFirebaseDatabase';
|
||||
|
||||
_offsetRef: Reference;
|
||||
_serverTimeOffset: number;
|
||||
_transactionHandler: TransactionHandler;
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options, true);
|
||||
constructor(app: App, options: Object = {}) {
|
||||
super(app, {
|
||||
events: NATIVE_EVENTS,
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
this._transactionHandler = new TransactionHandler(this);
|
||||
|
||||
if (this._options.persistence) {
|
||||
this._native.setPersistence(this._options.persistence);
|
||||
if (options.persistence) {
|
||||
getNativeModule(this).setPersistence(options.persistence);
|
||||
}
|
||||
|
||||
// server time listener
|
||||
|
@ -54,14 +64,14 @@ export default class Database extends ModuleBase {
|
|||
*
|
||||
*/
|
||||
goOnline(): void {
|
||||
this._native.goOnline();
|
||||
getNativeModule(this).goOnline();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
goOffline(): void {
|
||||
this._native.goOffline();
|
||||
getNativeModule(this).goOffline();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,8 +89,8 @@ export const statics = {
|
|||
TIMESTAMP: NativeModules.RNFirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' },
|
||||
} : {},
|
||||
enableLogging(enabled: boolean) {
|
||||
if (NativeModules[Database._NATIVE_MODULE]) {
|
||||
NativeModules[Database._NATIVE_MODULE].enableLogging(enabled);
|
||||
if (NativeModules[MODULE_NAME]) {
|
||||
NativeModules[MODULE_NAME].enableLogging(enabled);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
import Query from './query.js';
|
||||
import Snapshot from './snapshot';
|
||||
import Disconnect from './disconnect';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import ReferenceBase from '../../utils/ReferenceBase';
|
||||
|
||||
import {
|
||||
|
@ -17,10 +19,10 @@ import {
|
|||
generatePushID,
|
||||
} from '../../utils';
|
||||
|
||||
import INTERNALS from '../../utils/internals';
|
||||
import SyncTree from '../../utils/SyncTree';
|
||||
|
||||
import type Database from './';
|
||||
import type { DatabaseModifier, FirebaseError } from '../../types';
|
||||
import type SyncTree from '../../utils/SyncTree';
|
||||
|
||||
// track all event registrations by path
|
||||
let listeners = 0;
|
||||
|
@ -73,18 +75,18 @@ type DatabaseListener = {
|
|||
* @extends ReferenceBase
|
||||
*/
|
||||
export default class Reference extends ReferenceBase {
|
||||
_database: Object;
|
||||
_database: Database;
|
||||
_promise: ?Promise<*>;
|
||||
_query: Query;
|
||||
_refListeners: { [listenerId: number]: DatabaseListener };
|
||||
|
||||
constructor(database: Object, path: string, existingModifiers?: Array<DatabaseModifier>) {
|
||||
super(path, database);
|
||||
constructor(database: Database, path: string, existingModifiers?: Array<DatabaseModifier>) {
|
||||
super(path);
|
||||
this._promise = null;
|
||||
this._refListeners = {};
|
||||
this._database = database;
|
||||
this._query = new Query(this, path, existingModifiers);
|
||||
this.log.debug('Created new Reference', this._getRefKey());
|
||||
getLogger(database).debug('Created new Reference', this._getRefKey());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,7 +100,7 @@ export default class Reference extends ReferenceBase {
|
|||
* @returns {*}
|
||||
*/
|
||||
keepSynced(bool: boolean): Promise<void> {
|
||||
return this._database._native.keepSynced(this._getRefKey(), this.path, this._query.getModifiers(), bool);
|
||||
return getNativeModule(this._database).keepSynced(this._getRefKey(), this.path, this._query.getModifiers(), bool);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,7 +113,7 @@ export default class Reference extends ReferenceBase {
|
|||
*/
|
||||
set(value: any, onComplete?: Function): Promise<void> {
|
||||
return promiseOrCallback(
|
||||
this._database._native.set(this.path, this._serializeAnyType(value)),
|
||||
getNativeModule(this._database).set(this.path, this._serializeAnyType(value)),
|
||||
onComplete,
|
||||
);
|
||||
}
|
||||
|
@ -128,7 +130,7 @@ export default class Reference extends ReferenceBase {
|
|||
const _priority = this._serializeAnyType(priority);
|
||||
|
||||
return promiseOrCallback(
|
||||
this._database._native.setPriority(this.path, _priority),
|
||||
getNativeModule(this._database).setPriority(this.path, _priority),
|
||||
onComplete,
|
||||
);
|
||||
}
|
||||
|
@ -147,7 +149,7 @@ export default class Reference extends ReferenceBase {
|
|||
const _priority = this._serializeAnyType(priority);
|
||||
|
||||
return promiseOrCallback(
|
||||
this._database._native.setWithPriority(this.path, _value, _priority),
|
||||
getNativeModule(this._database).setWithPriority(this.path, _value, _priority),
|
||||
onComplete,
|
||||
);
|
||||
}
|
||||
|
@ -164,7 +166,7 @@ export default class Reference extends ReferenceBase {
|
|||
const value = this._serializeObject(val);
|
||||
|
||||
return promiseOrCallback(
|
||||
this._database._native.update(this.path, value),
|
||||
getNativeModule(this._database).update(this.path, value),
|
||||
onComplete,
|
||||
);
|
||||
}
|
||||
|
@ -178,7 +180,7 @@ export default class Reference extends ReferenceBase {
|
|||
*/
|
||||
remove(onComplete?: Function): Promise<void> {
|
||||
return promiseOrCallback(
|
||||
this._database._native.remove(this.path),
|
||||
getNativeModule(this._database).remove(this.path),
|
||||
onComplete,
|
||||
);
|
||||
}
|
||||
|
@ -234,7 +236,7 @@ export default class Reference extends ReferenceBase {
|
|||
cancelOrContext: (error: FirebaseError) => void,
|
||||
context?: Object,
|
||||
) {
|
||||
return this._database._native.once(this._getRefKey(), this.path, this._query.getModifiers(), eventName)
|
||||
return getNativeModule(this._database).once(this._getRefKey(), this.path, this._query.getModifiers(), eventName)
|
||||
.then(({ snapshot }) => {
|
||||
const _snapshot = new Snapshot(this, snapshot);
|
||||
|
||||
|
@ -269,7 +271,9 @@ export default class Reference extends ReferenceBase {
|
|||
// if callback provided then internally call the set promise with value
|
||||
if (isFunction(onComplete)) {
|
||||
return promise
|
||||
// $FlowBug: Reports that onComplete can change to null despite the null check: https://github.com/facebook/flow/issues/1655
|
||||
.then(() => onComplete(null, newRef))
|
||||
// $FlowBug: Reports that onComplete can change to null despite the null check: https://github.com/facebook/flow/issues/1655
|
||||
.catch(error => onComplete(error, null));
|
||||
}
|
||||
|
||||
|
@ -535,7 +539,7 @@ export default class Reference extends ReferenceBase {
|
|||
* @return {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 +550,7 @@ export default class Reference extends ReferenceBase {
|
|||
* @private
|
||||
*/
|
||||
_getRefKey(): string {
|
||||
return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instance of db logger
|
||||
*/
|
||||
get log() {
|
||||
return this._database.log;
|
||||
return `$${this._database.app.name}$/${this.path}$${this._query.queryIdentifier()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -626,7 +623,7 @@ export default class Reference extends ReferenceBase {
|
|||
*
|
||||
* {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#on}
|
||||
*/
|
||||
on(eventType: string, callback: () => any, cancelCallbackOrContext?: () => any, context?: Object): Function {
|
||||
on(eventType: string, callback: (Snapshot) => any, cancelCallbackOrContext?: (Object) => any | Object, context?: Object): Function {
|
||||
if (!eventType) {
|
||||
throw new Error('Query.on failed: Function called with 0 arguments. Expects at least 2.');
|
||||
}
|
||||
|
@ -659,36 +656,37 @@ export default class Reference extends ReferenceBase {
|
|||
ref: this,
|
||||
path: this.path,
|
||||
key: this._getRefKey(),
|
||||
appName: this._database._appName,
|
||||
appName: this._database.app.name,
|
||||
eventRegistrationKey,
|
||||
};
|
||||
|
||||
this._syncTree.addRegistration(registrationObj, _context ? callback.bind(_context) : callback);
|
||||
SyncTree.addRegistration({
|
||||
...registrationObj,
|
||||
listener: _context ? callback.bind(_context) : callback,
|
||||
});
|
||||
|
||||
if (isFunction(cancelCallbackOrContext)) {
|
||||
if (cancelCallbackOrContext && isFunction(cancelCallbackOrContext)) {
|
||||
// cancellations have their own separate registration
|
||||
// as these are one off events, and they're not guaranteed
|
||||
// to occur either, only happens on failure to register on native
|
||||
this._syncTree.addRegistration(
|
||||
{
|
||||
ref: this,
|
||||
once: true,
|
||||
path: this.path,
|
||||
key: this._getRefKey(),
|
||||
appName: this._database._appName,
|
||||
eventType: `${eventType}$cancelled`,
|
||||
eventRegistrationKey: registrationCancellationKey,
|
||||
},
|
||||
_context ? cancelCallbackOrContext.bind(_context) : cancelCallbackOrContext,
|
||||
);
|
||||
SyncTree.addRegistration({
|
||||
ref: this,
|
||||
once: true,
|
||||
path: this.path,
|
||||
key: this._getRefKey(),
|
||||
appName: this._database.app.name,
|
||||
eventType: `${eventType}$cancelled`,
|
||||
eventRegistrationKey: registrationCancellationKey,
|
||||
listener: _context ? cancelCallbackOrContext.bind(_context) : cancelCallbackOrContext,
|
||||
});
|
||||
}
|
||||
|
||||
// initialise the native listener if not already listening
|
||||
this._database._native.on({
|
||||
getNativeModule(this._database).on({
|
||||
eventType,
|
||||
path: this.path,
|
||||
key: this._getRefKey(),
|
||||
appName: this._database._appName,
|
||||
appName: this._database.app.name,
|
||||
modifiers: this._query.getModifiers(),
|
||||
hasCancellationCallback: isFunction(cancelCallbackOrContext),
|
||||
registration: {
|
||||
|
@ -726,7 +724,7 @@ export default class Reference extends ReferenceBase {
|
|||
if (!arguments.length) {
|
||||
// Firebase Docs:
|
||||
// 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 +745,25 @@ export default class Reference extends ReferenceBase {
|
|||
// remove the callback.
|
||||
// Remove only a single registration
|
||||
if (eventType && originalCallback) {
|
||||
const registration = this._syncTree.getOneByPathEventListener(this.path, eventType, originalCallback);
|
||||
const registration = SyncTree.getOneByPathEventListener(this.path, eventType, originalCallback);
|
||||
if (!registration) return [];
|
||||
|
||||
// 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
|
||||
// call multiple times to remove multiple registrations
|
||||
return this._syncTree.removeListenerRegistrations(originalCallback, [registration]);
|
||||
return SyncTree.removeListenerRegistrations(originalCallback, [registration]);
|
||||
}
|
||||
|
||||
// Firebase Docs:
|
||||
// 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(
|
||||
this._syncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`),
|
||||
SyncTree.removeListenersForRegistrations(
|
||||
SyncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`),
|
||||
);
|
||||
|
||||
return this._syncTree.removeListenersForRegistrations(registrations);
|
||||
}
|
||||
|
||||
get _syncTree(): SyncTree {
|
||||
return INTERNALS.SyncTree;
|
||||
return SyncTree.removeListenersForRegistrations(registrations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,24 +2,36 @@
|
|||
* @flow
|
||||
* Database Transaction representation wrapper
|
||||
*/
|
||||
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import type Database from './';
|
||||
|
||||
let transactionId = 0;
|
||||
|
||||
/**
|
||||
* Uses the push id generator to create a transaction id
|
||||
* @returns {number}
|
||||
* @private
|
||||
*/
|
||||
const generateTransactionId = (): number => {
|
||||
return transactionId++;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class TransactionHandler
|
||||
*/
|
||||
export default class TransactionHandler {
|
||||
_database: Database;
|
||||
_transactionListener: Function;
|
||||
_transactions: { [string]: Object }
|
||||
_transactions: { [number]: Object }
|
||||
|
||||
constructor(database: Database) {
|
||||
this._transactions = {};
|
||||
this._database = database;
|
||||
|
||||
this._transactionListener = this._database.addListener(
|
||||
this._database._getAppEventName('database_transaction_event'),
|
||||
this._transactionListener = SharedEventEmitter.addListener(
|
||||
getAppEventName(this._database, 'database_transaction_event'),
|
||||
this._handleTransactionEvent.bind(this),
|
||||
);
|
||||
}
|
||||
|
@ -32,7 +44,7 @@ export default class TransactionHandler {
|
|||
* @param applyLocally
|
||||
*/
|
||||
add(reference: Object, transactionUpdater: Function, onComplete?: Function, applyLocally?: boolean = false) {
|
||||
const id = this._generateTransactionId();
|
||||
const id = generateTransactionId();
|
||||
|
||||
this._transactions[id] = {
|
||||
id,
|
||||
|
@ -44,22 +56,13 @@ export default class TransactionHandler {
|
|||
started: true,
|
||||
};
|
||||
|
||||
this._database._native.transactionStart(reference.path, id, applyLocally);
|
||||
getNativeModule(this._database).transactionStart(reference.path, id, applyLocally);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNALS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Uses the push id generator to create a transaction id
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
_generateTransactionId(): string {
|
||||
return transactionId++;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param event
|
||||
|
@ -75,7 +78,7 @@ export default class TransactionHandler {
|
|||
case 'complete':
|
||||
return this._handleComplete(event);
|
||||
default:
|
||||
this.log.warn(`Unknown transaction event type: '${event.type}'`, event);
|
||||
getLogger(this._database).warn(`Unknown transaction event type: '${event.type}'`, event);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +104,7 @@ export default class TransactionHandler {
|
|||
abort = true;
|
||||
}
|
||||
|
||||
this._database._native.transactionTryCommit(id, { value: newValue, abort });
|
||||
getNativeModule(this._database).transactionTryCommit(id, { value: newValue, abort });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +118,7 @@ export default class TransactionHandler {
|
|||
if (transaction && !transaction.completed) {
|
||||
transaction.completed = true;
|
||||
try {
|
||||
transaction.onComplete(new Error(event.error.message, event.error.code), null);
|
||||
transaction.onComplete(event.error, false, null);
|
||||
} finally {
|
||||
setImmediate(() => {
|
||||
delete this._transactions[event.id];
|
||||
|
|
|
@ -3,22 +3,26 @@
|
|||
* Crash Reporting representation wrapper
|
||||
*/
|
||||
import ModuleBase from '../../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../../core/firebase-app';
|
||||
import type App from '../../core/firebase-app';
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseCrashlytics';
|
||||
export const NAMESPACE = 'crashlytics';
|
||||
|
||||
export default class Crashlytics extends ModuleBase {
|
||||
static _NAMESPACE = 'crashlytics';
|
||||
static _NATIVE_MODULE = 'RNFirebaseCrashlytics';
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a crash. Useful for testing your application is set up correctly.
|
||||
*/
|
||||
crash(): void {
|
||||
this._native.crash();
|
||||
getNativeModule(this).crash();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +30,7 @@ export default class Crashlytics extends ModuleBase {
|
|||
* @param {string} message
|
||||
*/
|
||||
log(message: string): void {
|
||||
this._native.log(message);
|
||||
getNativeModule(this).log(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,42 +39,42 @@ export default class Crashlytics extends ModuleBase {
|
|||
* @param {string} message
|
||||
*/
|
||||
recordError(code: number, message: string): void {
|
||||
this._native.recordError(code, message);
|
||||
getNativeModule(this).recordError(code, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a boolean value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setBoolValue(key: string, value: boolean): void {
|
||||
this._native.setBoolValue(key, value);
|
||||
getNativeModule(this).setBoolValue(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a float value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setFloatValue(key: string, value: number): void {
|
||||
this._native.setFloatValue(key, value);
|
||||
getNativeModule(this).setFloatValue(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an integer value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setIntValue(key: string, value: number): void {
|
||||
this._native.setIntValue(key, value);
|
||||
getNativeModule(this).setIntValue(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a string value to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setStringValue(key: string, value: string): void {
|
||||
this._native.setStringValue(key, value);
|
||||
getNativeModule(this).setStringValue(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user ID to show alongside any subsequent crash reports.
|
||||
*/
|
||||
setUserIdentifier(userId: string): void {
|
||||
this._native.setUserIdentifier(userId);
|
||||
getNativeModule(this).setUserIdentifier(userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,10 @@ import DocumentReference from './DocumentReference';
|
|||
import Query from './Query';
|
||||
import { firestoreAutoId } from '../../utils';
|
||||
|
||||
import type DocumentSnapshot from './DocumentSnapshot';
|
||||
import type Firestore from './';
|
||||
import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types';
|
||||
import type Path from './Path';
|
||||
import type { Observer, QueryListenOptions } from './Query';
|
||||
import type { Observer, ObserverOnError, ObserverOnNext, QueryListenOptions } from './Query';
|
||||
import type QuerySnapshot from './QuerySnapshot';
|
||||
|
||||
/**
|
||||
|
@ -75,9 +74,9 @@ export default class CollectionReference {
|
|||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void,
|
||||
observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void,
|
||||
onError?: (Object) => void,
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError,
|
||||
): () => void {
|
||||
return this._query.onSnapshot(optionsOrObserverOrOnNext, observerOrOnNextOrOnError, onError);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
import CollectionReference from './CollectionReference';
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import { buildNativeMap } from './utils/serialize';
|
||||
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { firestoreAutoId, isFunction, isObject, isString } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Firestore from './';
|
||||
import type { FirestoreNativeDocumentSnapshot, FirestoreWriteOptions } from '../../types';
|
||||
|
@ -65,12 +68,12 @@ export default class DocumentReference {
|
|||
}
|
||||
|
||||
delete(): Promise<void> {
|
||||
return this._firestore._native
|
||||
return getNativeModule(this._firestore)
|
||||
.documentDelete(this.path);
|
||||
}
|
||||
|
||||
get(): Promise<DocumentSnapshot> {
|
||||
return this._firestore._native
|
||||
return getNativeModule(this._firestore)
|
||||
.documentGet(this.path)
|
||||
.then(result => new DocumentSnapshot(this._firestore, result));
|
||||
}
|
||||
|
@ -80,15 +83,18 @@ export default class DocumentReference {
|
|||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError,
|
||||
) {
|
||||
let observer = {};
|
||||
let observer: Observer;
|
||||
let docListenOptions = {};
|
||||
// Called with: onNext, ?onError
|
||||
if (isFunction(optionsOrObserverOrOnNext)) {
|
||||
observer.next = optionsOrObserverOrOnNext;
|
||||
if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Second argument must be a valid function.');
|
||||
}
|
||||
observer.error = observerOrOnNextOrOnError;
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: optionsOrObserverOrOnNext,
|
||||
error: observerOrOnNextOrOnError,
|
||||
};
|
||||
} else if (optionsOrObserverOrOnNext && isObject(optionsOrObserverOrOnNext)) {
|
||||
// Called with: Observer
|
||||
if (optionsOrObserverOrOnNext.next) {
|
||||
|
@ -96,7 +102,11 @@ export default class DocumentReference {
|
|||
if (optionsOrObserverOrOnNext.error && !isFunction(optionsOrObserverOrOnNext.error)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.error must be a valid function.');
|
||||
}
|
||||
observer = optionsOrObserverOrOnNext;
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: optionsOrObserverOrOnNext.next,
|
||||
error: optionsOrObserverOrOnNext.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.');
|
||||
}
|
||||
|
@ -104,18 +114,24 @@ export default class DocumentReference {
|
|||
docListenOptions = optionsOrObserverOrOnNext;
|
||||
// Called with: Options, onNext, ?onError
|
||||
if (isFunction(observerOrOnNextOrOnError)) {
|
||||
observer.next = observerOrOnNextOrOnError;
|
||||
if (onError && !isFunction(onError)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Third argument must be a valid function.');
|
||||
}
|
||||
observer.error = onError;
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError,
|
||||
error: onError,
|
||||
};
|
||||
// Called with Options, Observer
|
||||
} else if (observerOrOnNextOrOnError && isObject(observerOrOnNextOrOnError) && observerOrOnNextOrOnError.next) {
|
||||
if (isFunction(observerOrOnNextOrOnError.next)) {
|
||||
if (observerOrOnNextOrOnError.error && !isFunction(observerOrOnNextOrOnError.error)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.error must be a valid function.');
|
||||
}
|
||||
observer = observerOrOnNextOrOnError;
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError.next,
|
||||
error: observerOrOnNextOrOnError.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.');
|
||||
}
|
||||
|
@ -136,21 +152,21 @@ export default class DocumentReference {
|
|||
};
|
||||
|
||||
// Listen to snapshot events
|
||||
this._firestore.on(
|
||||
this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`),
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`),
|
||||
listener,
|
||||
);
|
||||
|
||||
// Listen for snapshot error events
|
||||
if (observer.error) {
|
||||
this._firestore.on(
|
||||
this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`),
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`),
|
||||
observer.error,
|
||||
);
|
||||
}
|
||||
|
||||
// Add the native listener
|
||||
this._firestore._native
|
||||
getNativeModule(this._firestore)
|
||||
.documentOnSnapshot(this.path, listenerId, docListenOptions);
|
||||
|
||||
// Return an unsubscribe method
|
||||
|
@ -159,7 +175,7 @@ export default class DocumentReference {
|
|||
|
||||
set(data: Object, writeOptions?: FirestoreWriteOptions): Promise<void> {
|
||||
const nativeData = buildNativeMap(data);
|
||||
return this._firestore._native
|
||||
return getNativeModule(this._firestore)
|
||||
.documentSet(this.path, nativeData, writeOptions);
|
||||
}
|
||||
|
||||
|
@ -183,7 +199,7 @@ export default class DocumentReference {
|
|||
}
|
||||
}
|
||||
const nativeData = buildNativeMap(data);
|
||||
return this._firestore._native
|
||||
return getNativeModule(this._firestore)
|
||||
.documentUpdate(this.path, nativeData);
|
||||
}
|
||||
|
||||
|
@ -196,10 +212,10 @@ export default class DocumentReference {
|
|||
* @param listener
|
||||
*/
|
||||
_offDocumentSnapshot(listenerId: string, listener: Function) {
|
||||
this._firestore.log.info('Removing onDocumentSnapshot listener');
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), listener);
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`), listener);
|
||||
this._firestore._native
|
||||
getLogger(this._firestore).info('Removing onDocumentSnapshot listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener);
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), listener);
|
||||
getNativeModule(this._firestore)
|
||||
.documentOffSnapshot(this.path, listenerId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import QuerySnapshot from './QuerySnapshot';
|
||||
import { buildNativeArray, buildTypeMap } from './utils/serialize';
|
||||
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import { firestoreAutoId, isFunction, isObject } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Firestore from './';
|
||||
import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types';
|
||||
|
@ -51,9 +54,12 @@ export type QueryListenOptions = {
|
|||
includeQueryMetadataChanges: boolean,
|
||||
}
|
||||
|
||||
export type ObserverOnError = (Object) => void;
|
||||
export type ObserverOnNext = (QuerySnapshot) => void;
|
||||
|
||||
export type Observer = {
|
||||
next: (DocumentSnapshot) => void,
|
||||
error?: (Object) => void,
|
||||
error?: ObserverOnError,
|
||||
next: ObserverOnNext,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,7 +123,7 @@ export default class Query {
|
|||
}
|
||||
|
||||
get(): Promise<QuerySnapshot> {
|
||||
return this._firestore._native
|
||||
return getNativeModule(this._firestore)
|
||||
.collectionGet(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
|
@ -145,19 +151,22 @@ export default class Query {
|
|||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void,
|
||||
observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void,
|
||||
onError?: (Object) => void,
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError,
|
||||
) {
|
||||
let observer = {};
|
||||
let observer: Observer;
|
||||
let queryListenOptions = {};
|
||||
// Called with: onNext, ?onError
|
||||
if (isFunction(optionsOrObserverOrOnNext)) {
|
||||
observer.next = optionsOrObserverOrOnNext;
|
||||
if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) {
|
||||
throw new Error('Query.onSnapshot failed: Second argument must be a valid function.');
|
||||
}
|
||||
observer.error = observerOrOnNextOrOnError;
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: optionsOrObserverOrOnNext,
|
||||
error: observerOrOnNextOrOnError,
|
||||
};
|
||||
} else if (optionsOrObserverOrOnNext && isObject(optionsOrObserverOrOnNext)) {
|
||||
// Called with: Observer
|
||||
if (optionsOrObserverOrOnNext.next) {
|
||||
|
@ -165,7 +174,11 @@ export default class Query {
|
|||
if (optionsOrObserverOrOnNext.error && !isFunction(optionsOrObserverOrOnNext.error)) {
|
||||
throw new Error('Query.onSnapshot failed: Observer.error must be a valid function.');
|
||||
}
|
||||
observer = optionsOrObserverOrOnNext;
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: optionsOrObserverOrOnNext.next,
|
||||
error: optionsOrObserverOrOnNext.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.');
|
||||
}
|
||||
|
@ -173,18 +186,24 @@ export default class Query {
|
|||
queryListenOptions = optionsOrObserverOrOnNext;
|
||||
// Called with: Options, onNext, ?onError
|
||||
if (isFunction(observerOrOnNextOrOnError)) {
|
||||
observer.next = observerOrOnNextOrOnError;
|
||||
if (onError && !isFunction(onError)) {
|
||||
throw new Error('Query.onSnapshot failed: Third argument must be a valid function.');
|
||||
}
|
||||
observer.error = onError;
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError,
|
||||
error: onError,
|
||||
};
|
||||
// Called with Options, Observer
|
||||
} else if (observerOrOnNextOrOnError && isObject(observerOrOnNextOrOnError) && observerOrOnNextOrOnError.next) {
|
||||
if (isFunction(observerOrOnNextOrOnError.next)) {
|
||||
if (observerOrOnNextOrOnError.error && !isFunction(observerOrOnNextOrOnError.error)) {
|
||||
throw new Error('Query.onSnapshot failed: Observer.error must be a valid function.');
|
||||
}
|
||||
observer = observerOrOnNextOrOnError;
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError.next,
|
||||
error: observerOrOnNextOrOnError.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.');
|
||||
}
|
||||
|
@ -197,7 +216,6 @@ export default class Query {
|
|||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Called with invalid arguments.');
|
||||
}
|
||||
|
||||
const listenerId = firestoreAutoId();
|
||||
|
||||
const listener = (nativeQuerySnapshot) => {
|
||||
|
@ -206,21 +224,21 @@ export default class Query {
|
|||
};
|
||||
|
||||
// Listen to snapshot events
|
||||
this._firestore.on(
|
||||
this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`),
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`),
|
||||
listener,
|
||||
);
|
||||
|
||||
// Listen for snapshot error events
|
||||
if (observer.error) {
|
||||
this._firestore.on(
|
||||
this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`),
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`),
|
||||
observer.error,
|
||||
);
|
||||
}
|
||||
|
||||
// Add the native listener
|
||||
this._firestore._native
|
||||
getNativeModule(this._firestore)
|
||||
.collectionOnSnapshot(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
|
@ -334,10 +352,10 @@ export default class Query {
|
|||
* @param listener
|
||||
*/
|
||||
_offCollectionSnapshot(listenerId: string, listener: Function) {
|
||||
this._firestore.log.info('Removing onQuerySnapshot listener');
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`), listener);
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`), listener);
|
||||
this._firestore._native
|
||||
getLogger(this._firestore).info('Removing onQuerySnapshot listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`), listener);
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`), listener);
|
||||
getNativeModule(this._firestore)
|
||||
.collectionOffSnapshot(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
import { buildNativeMap } from './utils/serialize';
|
||||
import { isObject, isString } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type DocumentReference from './DocumentReference';
|
||||
import type Firestore from './';
|
||||
|
@ -29,8 +30,7 @@ export default class WriteBatch {
|
|||
}
|
||||
|
||||
commit(): Promise<void> {
|
||||
return this._firestore._native
|
||||
.documentBatch(this._writes);
|
||||
return getNativeModule(this._firestore).documentBatch(this._writes);
|
||||
}
|
||||
|
||||
delete(docRef: DocumentReference): WriteBatch {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
*/
|
||||
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 DocumentReference from './DocumentReference';
|
||||
import FieldValue from './FieldValue';
|
||||
|
@ -14,7 +15,7 @@ import WriteBatch from './WriteBatch';
|
|||
import INTERNALS from '../../utils/internals';
|
||||
|
||||
import type DocumentSnapshot from './DocumentSnapshot';
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
import type QuerySnapshot from './QuerySnapshot';
|
||||
|
||||
type CollectionSyncEvent = {
|
||||
|
@ -33,64 +34,41 @@ type DocumentSyncEvent = {
|
|||
path: string,
|
||||
}
|
||||
|
||||
class FirestoreInternalModule extends ModuleBase {
|
||||
static _NAMESPACE = 'firestore';
|
||||
static _NATIVE_MODULE = 'RNFirebaseFirestore';
|
||||
const NATIVE_EVENTS = [
|
||||
'firestore_collection_sync_event',
|
||||
'firestore_document_sync_event',
|
||||
];
|
||||
|
||||
_referencePath: Path;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
export const MODULE_NAME = 'RNFirebaseFirestore';
|
||||
export const NAMESPACE = 'firestore';
|
||||
|
||||
/**
|
||||
* @class Firestore
|
||||
*/
|
||||
export default class Firestore extends FirestoreInternalModule {
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options);
|
||||
export default class Firestore extends ModuleBase {
|
||||
_referencePath: Path;
|
||||
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
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 {
|
||||
|
@ -134,20 +112,46 @@ export default class Firestore extends FirestoreInternalModule {
|
|||
}
|
||||
|
||||
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 {
|
||||
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 = {
|
||||
FieldValue,
|
||||
GeoPoint,
|
||||
enableLogging(bool) {
|
||||
if (NativeModules[Firestore._NATIVE_MODULE]) {
|
||||
NativeModules[Firestore._NATIVE_MODULE].enableLogging(bool);
|
||||
enableLogging(enabled: boolean) {
|
||||
if (NativeModules[MODULE_NAME]) {
|
||||
NativeModules[MODULE_NAME].enableLogging(enabled);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -2,15 +2,24 @@
|
|||
* @flow
|
||||
* Dynamic Links representation wrapper
|
||||
*/
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import { areObjectKeysContainedInOther, isObject, isString } from './../../utils';
|
||||
import { SharedEventEmitter } from '../../utils/events';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { areObjectKeysContainedInOther, isObject, isString } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
const EVENT_TYPE = {
|
||||
Link: 'dynamic_link_received',
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
EVENT_TYPE.Link,
|
||||
];
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseLinks';
|
||||
export const NAMESPACE = 'links';
|
||||
|
||||
function validateParameters(parameters: Object): void {
|
||||
const suportedParametersObject = {
|
||||
dynamicLinkDomain: 'string',
|
||||
|
@ -62,11 +71,12 @@ function checkForMandatoryParameters(parameters: Object): void {
|
|||
* @class Links
|
||||
*/
|
||||
export default class Links extends ModuleBase {
|
||||
static _NAMESPACE = 'links';
|
||||
static _NATIVE_MODULE = 'RNFirebaseLinks';
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options, true);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
events: NATIVE_EVENTS,
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
}
|
||||
|
||||
get EVENT_TYPE(): Object {
|
||||
|
@ -78,7 +88,7 @@ export default class Links extends ModuleBase {
|
|||
* @returns {Promise.<String>}
|
||||
*/
|
||||
getInitialLink(): Promise<string> {
|
||||
return this._native.getInitialLink();
|
||||
return getNativeModule(this).getInitialLink();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +97,7 @@ export default class Links extends ModuleBase {
|
|||
* @returns {Function}
|
||||
*/
|
||||
onLink(listener: Function): () => any {
|
||||
const rnListener = this._eventEmitter.addListener(EVENT_TYPE.Link, listener);
|
||||
const rnListener = SharedEventEmitter.addListener(EVENT_TYPE.Link, listener);
|
||||
return () => rnListener.remove();
|
||||
}
|
||||
|
||||
|
@ -100,7 +110,7 @@ export default class Links extends ModuleBase {
|
|||
try {
|
||||
checkForMandatoryParameters(parameters);
|
||||
validateParameters(parameters);
|
||||
return this._native.createDynamicLink(parameters);
|
||||
return getNativeModule(this).createDynamicLink(parameters);
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
@ -115,7 +125,7 @@ export default class Links extends ModuleBase {
|
|||
try {
|
||||
checkForMandatoryParameters(parameters);
|
||||
validateParameters(parameters);
|
||||
return this._native.createShortDynamicLink(parameters);
|
||||
return getNativeModule(this).createShortDynamicLink(parameters);
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
* Messaging representation wrapper
|
||||
*/
|
||||
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 { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
const EVENT_TYPE = {
|
||||
RefreshToken: 'messaging_token_refreshed',
|
||||
|
@ -31,6 +33,11 @@ const WILL_PRESENT_RESULT = {
|
|||
None: 'UNNotificationPresentationOptionNone',
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
EVENT_TYPE.RefreshToken,
|
||||
EVENT_TYPE.Notification,
|
||||
];
|
||||
|
||||
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
|
||||
|
||||
/**
|
||||
|
@ -73,16 +80,19 @@ function finish(data) {
|
|||
}
|
||||
}
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseMessaging';
|
||||
export const NAMESPACE = 'messaging';
|
||||
|
||||
/**
|
||||
* @class Messaging
|
||||
*/
|
||||
export default class Messaging extends ModuleBase {
|
||||
static _NAMESPACE = 'messaging';
|
||||
static _NATIVE_MODULE = 'RNFirebaseMessaging';
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options, true);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
events: NATIVE_EVENTS,
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
}
|
||||
|
||||
get EVENT_TYPE(): Object {
|
||||
|
@ -106,7 +116,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {*}
|
||||
*/
|
||||
getInitialNotification(): Promise<Object> {
|
||||
return this._native.getInitialNotification();
|
||||
return getNativeModule(this).getInitialNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,7 +124,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {*|Promise.<String>}
|
||||
*/
|
||||
getToken(): Promise<string> {
|
||||
return this._native.getToken();
|
||||
return getNativeModule(this).getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +132,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {*|Promise.<*>}
|
||||
*/
|
||||
deleteInstanceId(): Promise<void> {
|
||||
return this._native.deleteInstanceId();
|
||||
return getNativeModule(this).deleteInstanceId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,7 +144,7 @@ export default class Messaging extends ModuleBase {
|
|||
const _notification = Object.assign({}, notification);
|
||||
_notification.id = _notification.id || new Date().getTime().toString();
|
||||
_notification.local_notification = true;
|
||||
return this._native.createLocalNotification(_notification);
|
||||
return getNativeModule(this).createLocalNotification(_notification);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,7 +156,7 @@ export default class Messaging extends ModuleBase {
|
|||
const _notification = Object.assign({}, notification);
|
||||
if (!notification.id) return Promise.reject(new Error('An id is required to schedule a local notification.'));
|
||||
_notification.local_notification = true;
|
||||
return this._native.scheduleLocalNotification(_notification);
|
||||
return getNativeModule(this).scheduleLocalNotification(_notification);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,7 +164,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {Promise.<Array>}
|
||||
*/
|
||||
getScheduledLocalNotifications(): Promise<Object[]> {
|
||||
return this._native.getScheduledLocalNotifications();
|
||||
return getNativeModule(this).getScheduledLocalNotifications();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,8 +175,8 @@ export default class Messaging extends ModuleBase {
|
|||
*/
|
||||
cancelLocalNotification(id: string): Promise<void> {
|
||||
if (!id) return Promise.reject(new Error('Missing notification id'));
|
||||
if (id === '*') return this._native.cancelAllLocalNotifications();
|
||||
return this._native.cancelLocalNotification(id);
|
||||
if (id === '*') return getNativeModule(this).cancelAllLocalNotifications();
|
||||
return getNativeModule(this).cancelLocalNotification(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,8 +187,8 @@ export default class Messaging extends ModuleBase {
|
|||
*/
|
||||
removeDeliveredNotification(id: string): Promise<void> {
|
||||
if (!id) return Promise.reject(new Error('Missing notification id'));
|
||||
if (id === '*') return this._native.removeAllDeliveredNotifications();
|
||||
return this._native.removeDeliveredNotification(id);
|
||||
if (id === '*') return getNativeModule(this).removeAllDeliveredNotifications();
|
||||
return getNativeModule(this).removeDeliveredNotification(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,7 +197,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {*|Promise.<*>}
|
||||
*/
|
||||
requestPermissions(): Promise<void> {
|
||||
return this._native.requestPermissions();
|
||||
return getNativeModule(this).requestPermissions();
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,7 +206,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @param n
|
||||
*/
|
||||
setBadgeNumber(n: number): void {
|
||||
this._native.setBadgeNumber(n);
|
||||
getNativeModule(this).setBadgeNumber(n);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,7 +214,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {Promise.<Number>}
|
||||
*/
|
||||
getBadgeNumber(): Promise<number> {
|
||||
return this._native.getBadgeNumber();
|
||||
return getNativeModule(this).getBadgeNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,7 +223,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {*}
|
||||
*/
|
||||
onMessage(listener: (Object) => any): () => any {
|
||||
const rnListener = this._eventEmitter.addListener(
|
||||
const rnListener = SharedEventEmitter.addListener(
|
||||
EVENT_TYPE.Notification,
|
||||
async (event) => {
|
||||
const data = {
|
||||
|
@ -236,7 +246,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @returns {*}
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -245,7 +255,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @param topic
|
||||
*/
|
||||
subscribeToTopic(topic: string): void {
|
||||
this._native.subscribeToTopic(topic);
|
||||
getNativeModule(this).subscribeToTopic(topic);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,7 +263,7 @@ export default class Messaging extends ModuleBase {
|
|||
* @param topic
|
||||
*/
|
||||
unsubscribeFromTopic(topic: string): void {
|
||||
this._native.unsubscribeFromTopic(topic);
|
||||
getNativeModule(this).unsubscribeFromTopic(topic);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -265,7 +275,7 @@ export default class Messaging extends ModuleBase {
|
|||
throw new Error('messaging().send requires an instance of RemoteMessage as the first argument.');
|
||||
}
|
||||
|
||||
return this._native.send(remoteMessage.toJSON());
|
||||
return getNativeModule(this).send(remoteMessage.toJSON());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,26 +2,27 @@
|
|||
* @flow
|
||||
* Trace representation wrapper
|
||||
*/
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import type PerformanceMonitoring from './';
|
||||
|
||||
export default class Trace {
|
||||
identifier: string;
|
||||
perf: PerformanceMonitoring;
|
||||
_perf: PerformanceMonitoring;
|
||||
|
||||
constructor(perf: PerformanceMonitoring, identifier: string) {
|
||||
this.perf = perf;
|
||||
this._perf = perf;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
start(): void {
|
||||
this.perf._native.start(this.identifier);
|
||||
getNativeModule(this._perf).start(this.identifier);
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
this.perf._native.stop(this.identifier);
|
||||
getNativeModule(this._perf).stop(this.identifier);
|
||||
}
|
||||
|
||||
incrementCounter(event: string): void {
|
||||
this.perf._native.incrementCounter(this.identifier, event);
|
||||
getNativeModule(this._perf).incrementCounter(this.identifier, event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,19 @@
|
|||
*/
|
||||
import Trace from './Trace';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
export const MODULE_NAME = 'RNFirebasePerformance';
|
||||
export const NAMESPACE = 'perf';
|
||||
|
||||
export default class PerformanceMonitoring extends ModuleBase {
|
||||
static _NAMESPACE = 'perf';
|
||||
static _NATIVE_MODULE = 'RNFirebasePerformance';
|
||||
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,7 +25,7 @@ export default class PerformanceMonitoring extends ModuleBase {
|
|||
* @returns {*}
|
||||
*/
|
||||
setPerformanceCollectionEnabled(enabled: boolean): void {
|
||||
this._native.setPerformanceCollectionEnabled(enabled);
|
||||
getNativeModule(this).setPerformanceCollectionEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,31 +5,43 @@
|
|||
import { NativeModules } from 'react-native';
|
||||
|
||||
import StorageRef from './reference';
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import { getAppEventName, SharedEventEmitter } from '../../utils/events';
|
||||
import { getLogger } from '../../utils/log';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type FirebaseApp from '../core/firebase-app';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
const FirebaseStorage = NativeModules.RNFirebaseStorage;
|
||||
|
||||
export default class Storage extends ModuleBase {
|
||||
static _NAMESPACE = 'storage';
|
||||
static _NATIVE_MODULE = 'RNFirebaseStorage';
|
||||
const NATIVE_EVENTS = [
|
||||
'storage_event',
|
||||
'storage_error',
|
||||
];
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseStorage';
|
||||
export const NAMESPACE = 'storage';
|
||||
|
||||
export default class Storage extends ModuleBase {
|
||||
/**
|
||||
*
|
||||
* @param firebaseApp
|
||||
* @param app
|
||||
* @param options
|
||||
*/
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options, true);
|
||||
constructor(app: App) {
|
||||
super(app, {
|
||||
events: NATIVE_EVENTS,
|
||||
moduleName: MODULE_NAME,
|
||||
namespace: NAMESPACE,
|
||||
});
|
||||
|
||||
this.addListener(
|
||||
this._getAppEventName('storage_event'),
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this, 'storage_event'),
|
||||
this._handleStorageEvent.bind(this),
|
||||
);
|
||||
|
||||
this.addListener(
|
||||
this._getAppEventName('storage_error'),
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this, 'storage_error'),
|
||||
this._handleStorageEvent.bind(this),
|
||||
);
|
||||
}
|
||||
|
@ -50,7 +62,7 @@ export default class Storage extends ModuleBase {
|
|||
* @param url
|
||||
* @returns {StorageReference}
|
||||
*/
|
||||
refFromURL(url: string): Promise<StorageRef> {
|
||||
refFromURL(url: string): StorageRef {
|
||||
// TODO don't think this is correct?
|
||||
return new StorageRef(this, `url::${url}`);
|
||||
}
|
||||
|
@ -61,7 +73,7 @@ export default class Storage extends ModuleBase {
|
|||
* @param time The new maximum operation retry time in milliseconds.
|
||||
*/
|
||||
setMaxOperationRetryTime(time: number): void {
|
||||
this._native.setMaxOperationRetryTime(time);
|
||||
getNativeModule(this).setMaxOperationRetryTime(time);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,7 +82,7 @@ export default class Storage extends ModuleBase {
|
|||
* @param time The new maximum upload retry time in milliseconds.
|
||||
*/
|
||||
setMaxUploadRetryTime(time: number): void {
|
||||
this._native.setMaxUploadRetryTime(time);
|
||||
getNativeModule(this).setMaxUploadRetryTime(time);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,38 +91,38 @@ export default class Storage extends ModuleBase {
|
|||
* @param time The new maximum download retry time in milliseconds.
|
||||
*/
|
||||
setMaxDownloadRetryTime(time: number): void {
|
||||
this._native.setMaxDownloadRetryTime(time);
|
||||
getNativeModule(this).setMaxDownloadRetryTime(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNALS
|
||||
*/
|
||||
_getSubEventName(path: string, eventName: string) {
|
||||
return this._getAppEventName(`${path}-${eventName}`);
|
||||
return getAppEventName(this, `${path}-${eventName}`);
|
||||
}
|
||||
|
||||
_handleStorageEvent(event: Object) {
|
||||
const { path, eventName } = event;
|
||||
const body = event.body || {};
|
||||
|
||||
this.log.debug('_handleStorageEvent: ', path, eventName, body);
|
||||
this.emit(this._getSubEventName(path, eventName), body);
|
||||
getLogger(this).debug('_handleStorageEvent: ', path, eventName, body);
|
||||
SharedEventEmitter.emit(this._getSubEventName(path, eventName), body);
|
||||
}
|
||||
|
||||
_handleStorageError(err: Object) {
|
||||
const { path, eventName } = err;
|
||||
const body = err.body || {};
|
||||
|
||||
this.log.debug('_handleStorageError ->', err);
|
||||
this.emit(this._getSubEventName(path, eventName), body);
|
||||
getLogger(this).debug('_handleStorageError ->', err);
|
||||
SharedEventEmitter.emit(this._getSubEventName(path, eventName), body);
|
||||
}
|
||||
|
||||
_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 {
|
||||
this.removeListener(this._getSubEventName(path, eventName), origCB);
|
||||
SharedEventEmitter.removeListener(this._getSubEventName(path, eventName), origCB);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
import ReferenceBase from '../../utils/ReferenceBase';
|
||||
import StorageTask, { UPLOAD_TASK, DOWNLOAD_TASK } from './task';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import type Storage from './';
|
||||
|
||||
|
||||
|
@ -14,7 +15,7 @@ export default class StorageReference extends ReferenceBase {
|
|||
_storage: Storage;
|
||||
|
||||
constructor(storage: Storage, path: string) {
|
||||
super(path, storage);
|
||||
super(path);
|
||||
this._storage = storage;
|
||||
}
|
||||
|
||||
|
@ -40,7 +41,7 @@ export default class StorageReference extends ReferenceBase {
|
|||
* @returns {Promise.<T>|*}
|
||||
*/
|
||||
delete(): Promise<void> {
|
||||
return this._storage._native.delete(this.path);
|
||||
return getNativeModule(this._storage).delete(this.path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +49,7 @@ export default class StorageReference extends ReferenceBase {
|
|||
* @returns {Promise.<T>|*}
|
||||
*/
|
||||
getDownloadURL(): Promise<string> {
|
||||
return this._storage._native.getDownloadURL(this.path);
|
||||
return getNativeModule(this._storage).getDownloadURL(this.path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,7 +57,7 @@ export default class StorageReference extends ReferenceBase {
|
|||
* @returns {Promise.<T>|*}
|
||||
*/
|
||||
getMetadata(): Promise<Object> {
|
||||
return this._storage._native.getMetadata(this.path);
|
||||
return getNativeModule(this._storage).getMetadata(this.path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +66,7 @@ export default class StorageReference extends ReferenceBase {
|
|||
* @returns {Promise.<T>|*}
|
||||
*/
|
||||
updateMetadata(metadata: Object = {}): Promise<Object> {
|
||||
return this._storage._native.updateMetadata(this.path, metadata);
|
||||
return getNativeModule(this._storage).updateMetadata(this.path, metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,7 +75,7 @@ export default class StorageReference extends ReferenceBase {
|
|||
* @return {Promise}
|
||||
*/
|
||||
downloadFile(filePath: string): Promise<Object> {
|
||||
return new StorageTask(DOWNLOAD_TASK, this._storage._native.downloadFile(this.path, filePath), this);
|
||||
return new StorageTask(DOWNLOAD_TASK, getNativeModule(this._storage).downloadFile(this.path, filePath), this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,6 +94,6 @@ export default class StorageReference extends ReferenceBase {
|
|||
*/
|
||||
putFile(filePath: Object, metadata: Object = {}): Promise<Object> {
|
||||
const _filePath = filePath.replace('file://', '');
|
||||
return new StorageTask(UPLOAD_TASK, this._module._native.putFile(this.path, _filePath, metadata), this);
|
||||
return new StorageTask(UPLOAD_TASK, getNativeModule(this._storage).putFile(this.path, _filePath, metadata), this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import { NativeModules } from 'react-native';
|
||||
// import { version as ReactVersion } from 'react';
|
||||
// import ReactNativeVersion from 'react-native/Libraries/Core/ReactNativeVersion';
|
||||
|
||||
import INTERNALS from '../../utils/internals';
|
||||
import { isIOS } from '../../utils';
|
||||
import ModuleBase from '../../utils/ModuleBase';
|
||||
|
@ -18,34 +17,31 @@ type GoogleApiAvailabilityType = {
|
|||
error?: string
|
||||
}
|
||||
|
||||
export default class RNFirebaseUtils extends ModuleBase {
|
||||
static _NAMESPACE = 'utils';
|
||||
static _NATIVE_DISABLED = true;
|
||||
static _NATIVE_MODULE = 'RNFirebaseUtils';
|
||||
export const MODULE_NAME = 'RNFirebaseUtils';
|
||||
export const NAMESPACE = 'utils';
|
||||
|
||||
export default class RNFirebaseUtils extends ModuleBase {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
checkPlayServicesAvailability() {
|
||||
if (isIOS) return null;
|
||||
if (isIOS) return;
|
||||
|
||||
const code = this.playServicesAvailability.code;
|
||||
const { status } = this.playServicesAvailability;
|
||||
|
||||
if (!this.playServicesAvailability.isAvailable) {
|
||||
if (INTERNALS.OPTIONS.promptOnMissingPlayServices && this.playServicesAvailability.isUserResolvableError) {
|
||||
this.promptForPlayServices();
|
||||
} else {
|
||||
const error = INTERNALS.STRINGS.ERROR_PLAY_SERVICES(code);
|
||||
const error = INTERNALS.STRINGS.ERROR_PLAY_SERVICES(status);
|
||||
if (INTERNALS.OPTIONS.errorOnMissingPlayServices) {
|
||||
if (code === 2) console.warn(error); // only warn if it exists but may need an update
|
||||
if (status === 2) console.warn(error); // only warn if it exists but may need an update
|
||||
else throw new Error(error);
|
||||
} else {
|
||||
console.warn(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
promptForPlayServices() {
|
||||
|
@ -63,41 +59,13 @@ export default class RNFirebaseUtils extends ModuleBase {
|
|||
return FirebaseCoreModule.makePlayServicesAvailable();
|
||||
}
|
||||
|
||||
get sharedEventEmitter(): Object {
|
||||
return INTERNALS.SharedEventEmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the global logging level for all logs.
|
||||
*
|
||||
* @param booleanOrDebugString
|
||||
* @param logLevel
|
||||
*/
|
||||
set 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);
|
||||
set logLevel(logLevel: string) {
|
||||
INTERNALS.OPTIONS.logLevel = logLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,7 +98,6 @@ export default class RNFirebaseUtils extends ModuleBase {
|
|||
|
||||
|
||||
export const statics = {
|
||||
DEFAULT_APP_NAME: INTERNALS.STRINGS.DEFAULT_APP_NAME,
|
||||
// VERSIONS: {
|
||||
// react: ReactVersion,
|
||||
// 'react-native': Object.values(ReactNativeVersion.version).slice(0, 3).join('.'),
|
||||
|
|
|
@ -40,7 +40,18 @@ export type FirebaseError = {
|
|||
|
||||
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'
|
||||
| 'utils';
|
||||
|
||||
|
|
|
@ -1,174 +1,42 @@
|
|||
/**
|
||||
* @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 { FirebaseModuleName } 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,
|
||||
},
|
||||
};
|
||||
import type App from '../modules/core/firebase-app';
|
||||
import type { FirebaseModuleConfig, FirebaseNamespace } from '../types';
|
||||
|
||||
export default class ModuleBase {
|
||||
_native: Object;
|
||||
_module: string;
|
||||
_options: Object;
|
||||
_appName: string;
|
||||
_namespace: string;
|
||||
_firebaseApp: FirebaseApp;
|
||||
_eventEmitter: Object;
|
||||
static _NAMESPACE: FirebaseModuleName;
|
||||
static _NATIVE_MODULE: string;
|
||||
_app: App;
|
||||
namespace: FirebaseNamespace;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param firebaseApp
|
||||
* @param options
|
||||
* @param withEventEmitter
|
||||
* @param app
|
||||
* @param config
|
||||
*/
|
||||
constructor(firebaseApp: FirebaseApp, options: Object, withEventEmitter: boolean = false) {
|
||||
this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', '');
|
||||
this._firebaseApp = firebaseApp;
|
||||
this._appName = firebaseApp._name;
|
||||
this._namespace = `${this._appName}:${this._module}`;
|
||||
this._options = Object.assign({}, DEFAULTS[this._module] || {}, options);
|
||||
constructor(app: App, config: FirebaseModuleConfig) {
|
||||
if (!config.moduleName) {
|
||||
throw new Error('Missing module name');
|
||||
}
|
||||
if (!config.namespace) {
|
||||
throw new Error('Missing namespace');
|
||||
}
|
||||
const { moduleName } = config;
|
||||
this._app = app;
|
||||
this.namespace = config.namespace;
|
||||
|
||||
// check if native module exists as all native
|
||||
// modules are now optionally part of build
|
||||
const nativeModule = NativeModules[this.constructor._NATIVE_MODULE];
|
||||
|
||||
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);
|
||||
}
|
||||
initialiseNativeModule(this, config);
|
||||
initialiseLogger(this, `${app.name}:${moduleName.replace('RNFirebase', '')}`);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FirebaseApp instance for current module
|
||||
* Returns the App instance for current module
|
||||
* @return {*}
|
||||
*/
|
||||
get app(): 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);
|
||||
get app(): App {
|
||||
return this._app;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
/**
|
||||
* @flow
|
||||
*/
|
||||
import Log from './log';
|
||||
|
||||
import type Database from '../modules/database';
|
||||
import type Storage from '../modules/storage';
|
||||
|
||||
export default class ReferenceBase {
|
||||
_module: Database | Storage;
|
||||
path: string;
|
||||
|
||||
constructor(path: string, module: Database | Storage) {
|
||||
this._module = module;
|
||||
constructor(path: string) {
|
||||
this.path = path || '/';
|
||||
}
|
||||
|
||||
|
@ -24,8 +17,4 @@ export default class ReferenceBase {
|
|||
get key(): string | null {
|
||||
return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
get log(): Log {
|
||||
return this._module.log;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
/**
|
||||
* @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 DatabaseReference from '../modules/database/reference';
|
||||
import { isString, nativeToJSError } from '../utils';
|
||||
|
||||
type Listener = (DatabaseSnapshot) => any;
|
||||
|
||||
type Registration = {
|
||||
key: string,
|
||||
path: string,
|
||||
once?: boolean,
|
||||
appName: string,
|
||||
eventType: string,
|
||||
listener: Function,
|
||||
listener: Listener,
|
||||
eventRegistrationKey: string,
|
||||
ref: DatabaseReference,
|
||||
}
|
||||
|
@ -23,21 +25,21 @@ type Registration = {
|
|||
* Internally used to manage firebase database realtime event
|
||||
* subscriptions and keep the listeners in sync in js vs native.
|
||||
*/
|
||||
export default class SyncTree {
|
||||
_databaseNative: Object;
|
||||
class SyncTree {
|
||||
_nativeEmitter: NativeEventEmitter;
|
||||
_reverseLookup: { [string]: Registration };
|
||||
_tree: { [string]: { [string]: Array }};
|
||||
_tree: { [string]: { [string]: { [string]: Listener }}};
|
||||
|
||||
constructor(databaseNative: Object) {
|
||||
constructor() {
|
||||
this._tree = {};
|
||||
this._reverseLookup = {};
|
||||
this._databaseNative = databaseNative;
|
||||
this._nativeEmitter = new NativeEventEmitter(databaseNative);
|
||||
this._nativeEmitter.addListener(
|
||||
'database_sync_event',
|
||||
this._handleSyncEvent.bind(this),
|
||||
);
|
||||
if (NativeModules.RNFirebaseDatabase) {
|
||||
this._nativeEmitter = new NativeEventEmitter(NativeModules.RNFirebaseDatabase);
|
||||
this._nativeEmitter.addListener(
|
||||
'database_sync_event',
|
||||
this._handleSyncEvent.bind(this),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,13 +73,13 @@ export default class SyncTree {
|
|||
// notify native that the registration
|
||||
// no longer exists so it can remove
|
||||
// the native listeners
|
||||
return this._databaseNative.off(key, eventRegistrationKey);
|
||||
return NativeModules.RNFirebaseDatabase.off(key, eventRegistrationKey);
|
||||
}
|
||||
|
||||
const { snapshot, previousChildName } = event.data;
|
||||
|
||||
// forward on to users .on(successCallback <-- listener
|
||||
return INTERNALS.SharedEventEmitter.emit(
|
||||
return SharedEventEmitter.emit(
|
||||
eventRegistrationKey,
|
||||
new DatabaseSnapshot(registration.ref, snapshot),
|
||||
previousChildName,
|
||||
|
@ -104,7 +106,7 @@ export default class SyncTree {
|
|||
const error = nativeToJSError(code, message, { ref: registration.ref });
|
||||
|
||||
// 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
|
||||
// event then it's guaranteed that they'll be no further value events
|
||||
|
@ -128,17 +130,17 @@ export default class SyncTree {
|
|||
* @param registrations
|
||||
* @return {number}
|
||||
*/
|
||||
removeListenersForRegistrations(registrations: string | string[]) {
|
||||
removeListenersForRegistrations(registrations: string | string[]): number {
|
||||
if (isString(registrations)) {
|
||||
this.removeRegistration(registrations);
|
||||
INTERNALS.SharedEventEmitter.removeAllListeners(registrations);
|
||||
SharedEventEmitter.removeAllListeners(registrations);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!Array.isArray(registrations)) return 0;
|
||||
for (let i = 0, len = registrations.length; i < len; i++) {
|
||||
this.removeRegistration(registrations[i]);
|
||||
INTERNALS.SharedEventEmitter.removeAllListeners(registrations[i]);
|
||||
SharedEventEmitter.removeAllListeners(registrations[i]);
|
||||
}
|
||||
|
||||
return registrations.length;
|
||||
|
@ -151,13 +153,13 @@ export default class SyncTree {
|
|||
* @param registrations
|
||||
* @return {Array} array of registrations removed
|
||||
*/
|
||||
removeListenerRegistrations(listener, registrations: string[]) {
|
||||
removeListenerRegistrations(listener: () => any, registrations: string[]) {
|
||||
if (!Array.isArray(registrations)) return [];
|
||||
const removed = [];
|
||||
|
||||
for (let i = 0, len = registrations.length; i < len; i++) {
|
||||
const registration = registrations[i];
|
||||
const subscriptions = INTERNALS.SharedEventEmitter._subscriber.getSubscriptionsForType(registration);
|
||||
const subscriptions = SharedEventEmitter._subscriber.getSubscriptionsForType(registration);
|
||||
if (subscriptions) {
|
||||
for (let j = 0, l = subscriptions.length; j < l; j++) {
|
||||
const subscription = subscriptions[j];
|
||||
|
@ -181,7 +183,7 @@ export default class SyncTree {
|
|||
* @param path
|
||||
* @return {Array}
|
||||
*/
|
||||
getRegistrationsByPath(path: string): Array {
|
||||
getRegistrationsByPath(path: string): string[] {
|
||||
const out = [];
|
||||
const eventKeys = Object.keys(this._tree[path] || {});
|
||||
|
||||
|
@ -199,7 +201,7 @@ export default class SyncTree {
|
|||
* @param eventType
|
||||
* @return {Array}
|
||||
*/
|
||||
getRegistrationsByPathEvent(path: string, eventType: string): Array {
|
||||
getRegistrationsByPathEvent(path: string, eventType: string): string[] {
|
||||
if (!this._tree[path]) return [];
|
||||
if (!this._tree[path][eventType]) return [];
|
||||
|
||||
|
@ -214,9 +216,9 @@ export default class SyncTree {
|
|||
* @param listener
|
||||
* @return {Array}
|
||||
*/
|
||||
getOneByPathEventListener(path: string, eventType: string, listener: Function): Array {
|
||||
if (!this._tree[path]) return [];
|
||||
if (!this._tree[path][eventType]) return [];
|
||||
getOneByPathEventListener(path: string, eventType: string, listener: Function): ?string {
|
||||
if (!this._tree[path]) return null;
|
||||
if (!this._tree[path][eventType]) return null;
|
||||
|
||||
const registrationsForPathEvent = Object.entries(this._tree[path][eventType]);
|
||||
|
||||
|
@ -236,27 +238,28 @@ export default class SyncTree {
|
|||
* @param listener
|
||||
* @return {String}
|
||||
*/
|
||||
addRegistration(parameters: Registration, listener: Function): string {
|
||||
addRegistration(registration: Registration): string {
|
||||
const {
|
||||
path,
|
||||
eventType,
|
||||
eventRegistrationKey,
|
||||
eventType,
|
||||
listener,
|
||||
once,
|
||||
} = parameters;
|
||||
path,
|
||||
} = registration;
|
||||
|
||||
if (!this._tree[path]) this._tree[path] = {};
|
||||
if (!this._tree[path][eventType]) this._tree[path][eventType] = {};
|
||||
|
||||
this._tree[path][eventType][eventRegistrationKey] = listener;
|
||||
this._reverseLookup[eventRegistrationKey] = Object.assign({ listener }, parameters);
|
||||
this._reverseLookup[eventRegistrationKey] = registration;
|
||||
|
||||
if (once) {
|
||||
INTERNALS.SharedEventEmitter.once(
|
||||
SharedEventEmitter.once(
|
||||
eventRegistrationKey,
|
||||
this._onOnceRemoveRegistration(eventRegistrationKey, listener),
|
||||
);
|
||||
} else {
|
||||
INTERNALS.SharedEventEmitter.addListener(eventRegistrationKey, listener);
|
||||
SharedEventEmitter.addListener(eventRegistrationKey, listener);
|
||||
}
|
||||
|
||||
return eventRegistrationKey;
|
||||
|
@ -287,7 +290,7 @@ export default class SyncTree {
|
|||
// automatically unsubscribed on native when the first event is sent
|
||||
const registrationObj = this._reverseLookup[registration];
|
||||
if (registrationObj && !once) {
|
||||
this._databaseNative.off(registrationObj.key, registration);
|
||||
NativeModules.RNFirebaseDatabase.off(registrationObj.key, registration);
|
||||
}
|
||||
|
||||
delete this._tree[path][eventType][registration];
|
||||
|
@ -305,9 +308,11 @@ export default class SyncTree {
|
|||
* @private
|
||||
*/
|
||||
_onOnceRemoveRegistration(registration, listener) {
|
||||
return (...args) => {
|
||||
return (...args: any[]) => {
|
||||
this.removeRegistration(registration);
|
||||
listener(...args);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default new SyncTree();
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
* @flow
|
||||
*/
|
||||
import { NativeModules } from 'react-native';
|
||||
import App 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]: App } = {};
|
||||
const APP_MODULES: { [App]: { [string]: FirebaseModule }} = {};
|
||||
const DEFAULT_APP_NAME = '[DEFAULT]';
|
||||
|
||||
export default {
|
||||
DEFAULT_APP_NAME,
|
||||
|
||||
app(name?: string): App {
|
||||
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<App> {
|
||||
// $FlowBug: Object.values always returns mixed type: https://github.com/facebook/flow/issues/2221
|
||||
return Object.values(APPS);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param statics
|
||||
* @param InstanceClass
|
||||
* @return {function()}
|
||||
* @private
|
||||
*/
|
||||
appModule<M: FirebaseModule>(app: App, namespace: FirebaseNamespace, InstanceClass: Class<M>): () => FirebaseModule {
|
||||
return (): M => {
|
||||
if (!APP_MODULES[app]) {
|
||||
APP_MODULES[app] = {};
|
||||
}
|
||||
|
||||
if (isAndroid && namespace !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) {
|
||||
INTERNALS.FLAGS.checkedPlayServices = true;
|
||||
this.utils().checkPlayServicesAvailability();
|
||||
}
|
||||
|
||||
if (!APP_MODULES[app][namespace]) {
|
||||
APP_MODULES[app][namespace] = new InstanceClass(app, app.options);
|
||||
}
|
||||
|
||||
return APP_MODULES[app][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): App {
|
||||
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 App(_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 App(app.name, options, true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param statics
|
||||
* @param InstanceClass
|
||||
* @return {function(App=)}
|
||||
*/
|
||||
moduleAndStatics<M: FirebaseModule, S: FirebaseStatics>(namespace: FirebaseNamespace, statics: S, moduleName: FirebaseModuleName): FirebaseModuleAndStatics<M, S> {
|
||||
const getModule = (app?: App): FirebaseModule => {
|
||||
let _app = app;
|
||||
|
||||
// throw an error if it's not a valid app instance
|
||||
if (_app && !(_app instanceof App)) 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(DEFAULT_APP_NAME);
|
||||
if (namespace === 'crashlytics') {
|
||||
return _app.fabric[namespace]();
|
||||
}
|
||||
// $FlowBug: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323
|
||||
const module = _app[namespace];
|
||||
return module();
|
||||
};
|
||||
|
||||
return Object.assign(getModule, statics, {
|
||||
nativeModuleExists: !!NativeModules[moduleName],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -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.app.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]);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -340,25 +340,6 @@ export function nativeToJSError(code: string, message: string, additionalProps?:
|
|||
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
|
||||
|
@ -390,21 +371,21 @@ export function objectToUniqueId(object: Object): string {
|
|||
* @param optionalCallback
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function promiseOrCallback(promise: Promise<*>, optionalCallback?: Function) {
|
||||
export function promiseOrCallback(promise: Promise<*>, optionalCallback?: Function): Promise<*> {
|
||||
if (!isFunction(optionalCallback)) return promise;
|
||||
|
||||
return promise.then((result) => {
|
||||
// some of firebase internal tests & methods only check/return one arg
|
||||
// see https://github.com/firebase/firebase-js-sdk/blob/master/src/utils/promise.ts#L62
|
||||
if (optionalCallback.length === 1) {
|
||||
if (optionalCallback && optionalCallback.length === 1) {
|
||||
optionalCallback(null);
|
||||
} else {
|
||||
} else if (optionalCallback) {
|
||||
optionalCallback(null, result);
|
||||
}
|
||||
|
||||
return Promise.resolve(result);
|
||||
}).catch((error) => {
|
||||
optionalCallback(error);
|
||||
if (optionalCallback) optionalCallback(error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
/**
|
||||
* @flow
|
||||
*/
|
||||
import { Platform, NativeModules } 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]';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
const NAMESPACE_PODS = {
|
||||
admob: 'Firebase/AdMob',
|
||||
|
@ -29,34 +21,38 @@ const GRADLE_DEPS = {
|
|||
};
|
||||
|
||||
const PLAY_SERVICES_CODES = {
|
||||
// $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380
|
||||
1: {
|
||||
code: 'SERVICE_MISSING',
|
||||
message: 'Google Play services is missing on this device.',
|
||||
},
|
||||
// $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380
|
||||
2: {
|
||||
code: 'SERVICE_VERSION_UPDATE_REQUIRED',
|
||||
message: 'The installed version of Google Play services on this device is out of date.',
|
||||
},
|
||||
// $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380
|
||||
3: {
|
||||
code: 'SERVICE_DISABLED',
|
||||
message: 'The installed version of Google Play services has been disabled on this device.',
|
||||
},
|
||||
// $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380
|
||||
9: {
|
||||
code: 'SERVICE_INVALID',
|
||||
message: 'The version of the Google Play services installed on this device is not authentic.',
|
||||
},
|
||||
// $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380
|
||||
18: {
|
||||
code: 'SERVICE_UPDATING',
|
||||
message: 'Google Play services is currently being updated on this device.',
|
||||
},
|
||||
// $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380
|
||||
19: {
|
||||
code: 'SERVICE_MISSING_PERMISSION',
|
||||
message: 'Google Play service doesn\'t have one or more required permissions.',
|
||||
},
|
||||
};
|
||||
|
||||
const APPS: { [string]: FirebaseApp } = {};
|
||||
|
||||
export default {
|
||||
// default options
|
||||
OPTIONS: {
|
||||
|
@ -69,9 +65,6 @@ export default {
|
|||
checkedPlayServices: false,
|
||||
},
|
||||
|
||||
// track all initialized firebase apps
|
||||
APPS,
|
||||
|
||||
STRINGS: {
|
||||
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.',
|
||||
|
@ -174,7 +167,7 @@ export default {
|
|||
* @return {string}
|
||||
*/
|
||||
ERROR_NOT_APP(namespace: string) {
|
||||
return `Invalid FirebaseApp instance passed to firebase.${namespace}(app <--).`;
|
||||
return `Invalid App instance passed to firebase.${namespace}(app <--).`;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -194,8 +187,8 @@ export default {
|
|||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_UNSUPPORTED_MODULE_METHOD(module: Class<ModuleBase>, method: string) {
|
||||
return `firebase.${module._NAMESPACE}().${method}() is unsupported by the native Firebase SDKs.`;
|
||||
ERROR_UNSUPPORTED_MODULE_METHOD(namespace: string, method: string) {
|
||||
return `firebase.${namespace}().${method}() is unsupported by the native Firebase SDKs.`;
|
||||
},
|
||||
|
||||
|
||||
|
@ -222,24 +215,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:' +
|
||||
'\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;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,12 +1,34 @@
|
|||
/*
|
||||
* @flow
|
||||
*/
|
||||
import { windowOrGlobal } from './';
|
||||
|
||||
import type ModuleBase from './ModuleBase';
|
||||
|
||||
((base) => {
|
||||
window = base || window;
|
||||
// $FlowFixMe: Why are we using localStorage at all?
|
||||
if (!window.localStorage) window.localStorage = {};
|
||||
})(windowOrGlobal);
|
||||
|
||||
// clean up time
|
||||
|
||||
const NATIVE_LOGGERS: { [string]: Object } = {};
|
||||
|
||||
const getModuleKey = (module: ModuleBase): string => `${module.app.name}:${module.namespace}`;
|
||||
|
||||
export const getLogger = (module: ModuleBase) => {
|
||||
const key = getModuleKey(module);
|
||||
return NATIVE_LOGGERS[key];
|
||||
};
|
||||
|
||||
export const initialiseLogger = (module: ModuleBase, logNamespace: string) => {
|
||||
const key = getModuleKey(module);
|
||||
if (!NATIVE_LOGGERS[key]) {
|
||||
NATIVE_LOGGERS[key] = require('bows')(`🔥 ${logNamespace.toUpperCase()}`);
|
||||
}
|
||||
};
|
||||
|
||||
export default class Log {
|
||||
static createLogger(namespace) {
|
||||
return require('bows')(namespace);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* @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: { [string]: 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;
|
||||
};
|
||||
|
||||
const getModuleKey = (module: ModuleBase): string => `${module.app.name}:${module.namespace}`;
|
||||
|
||||
export const getNativeModule = (module: ModuleBase): Object => {
|
||||
const key = getModuleKey(module);
|
||||
return NATIVE_MODULES[key];
|
||||
};
|
||||
|
||||
export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModuleConfig): Object => {
|
||||
const { moduleName, namespace } = config;
|
||||
const nativeModule = NativeModules[moduleName];
|
||||
const key = getModuleKey(module);
|
||||
|
||||
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[key] = nativeModule;
|
||||
} else {
|
||||
NATIVE_MODULES[key] = nativeWithApp(module.app.name, nativeModule);
|
||||
}
|
||||
|
||||
initialiseNativeModuleEventEmitter(module, config);
|
||||
|
||||
return NATIVE_MODULES[key];
|
||||
};
|
|
@ -40,7 +40,7 @@ const ios = {
|
|||
|
||||
const instances = {
|
||||
web: firebase.initializeApp(config),
|
||||
native: RNfirebase.app(),
|
||||
native: RNfirebase,
|
||||
another: RNfirebase.initializeApp(Platform.OS === 'ios' ? ios : android, 'anotherApp'),
|
||||
};
|
||||
|
||||
|
|
|
@ -53,8 +53,7 @@ function coreTests({ describe, it }) {
|
|||
|
||||
it('it should provide an array of apps', () => {
|
||||
should.equal(!!RNFirebase.apps.length, true);
|
||||
should.equal(RNFirebase.apps[0]._name, RNFirebase.utils.DEFAULT_APP_NAME);
|
||||
should.equal(RNFirebase.apps[0].name, '[DEFAULT]');
|
||||
should.equal(RNFirebase.apps.includes(RNFirebase.app('[DEFAULT]')), true);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue