2017-03-09 15:26:28 +00:00
#import "RNFirebaseDatabase.h"
2017-05-25 16:00:12 +01:00
#if __has_include(<FirebaseDatabase/FIRDatabase.h>)
2017-08-14 11:05:49 +01:00
2017-08-17 17:32:09 +01:00
#import <Firebase.h>
2017-07-19 16:02:26 +01:00
#import "RNFirebaseDatabaseReference.h"
#import "RNFirebaseEvents.h"
2017-10-26 11:55:07 +01:00
#import "RNFirebaseUtil.h"
2017-03-25 00:59:27 +00:00
2017-03-09 15:26:28 +00:00
@implementation RNFirebaseDatabase
2017-05-25 16:00:12 +01:00
RCT_EXPORT_MODULE ();
2017-03-09 15:26:28 +00:00
2018-05-15 10:02:18 +01:00
// Run on a different thread
- ( dispatch_queue_t ) methodQueue {
return dispatch_queue_create ( "io.invertase.react-native-firebase.database" , DISPATCH_QUEUE_SERIAL );
}
2017-08-14 11:05:49 +01:00
2017-05-25 16:00:12 +01:00
- ( id ) init {
2017-03-09 15:26:28 +00:00
self = [ super init ];
if ( self != nil ) {
_dbReferences = [[ NSMutableDictionary alloc ] init ];
2017-03-25 00:59:27 +00:00
_transactions = [[ NSMutableDictionary alloc ] init ];
2018-05-15 10:02:18 +01:00
_transactionQueue = dispatch_queue_create ( "io.invertase.react-native-firebase.database.transactions" , DISPATCH_QUEUE_CONCURRENT );
2017-03-09 15:26:28 +00:00
}
return self ;
}
2017-11-21 15:37:05 -08:00
RCT_EXPORT_METHOD ( goOnline :( NSString * ) appDisplayName
dbURL :( NSString * ) dbURL ) {
[[ RNFirebaseDatabase getDatabaseForApp : appDisplayName URL : dbURL ] goOnline ];
2017-03-25 00:59:27 +00:00
}
2017-03-09 15:26:28 +00:00
2017-11-21 15:37:05 -08:00
RCT_EXPORT_METHOD ( goOffline :( NSString * ) appDisplayName
dbURL :( NSString * ) dbURL ) {
[[ RNFirebaseDatabase getDatabaseForApp : appDisplayName URL : dbURL ] goOffline ];
2017-08-02 16:51:00 +01:00
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( setPersistence :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
state :( BOOL ) state ) {
2017-11-21 15:37:05 -08:00
[ RNFirebaseDatabase getDatabaseForApp : appDisplayName URL : dbURL ]. persistenceEnabled = state ;
2017-08-02 16:51:00 +01:00
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( setPersistenceCacheSizeBytes :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
size :( NSInteger * ) size ) {
2017-11-21 15:37:05 -08:00
[ RNFirebaseDatabase getDatabaseForApp : appDisplayName URL : dbURL ]. persistenceCacheSizeBytes = ( NSUInteger ) size ;
2017-11-08 11:32:18 +00:00
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( enableLogging :( BOOL ) enabled ) {
2017-11-08 11:15:24 +00:00
[ FIRDatabase setLoggingEnabled : enabled ];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( keepSynced :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
key :( NSString * ) key
path :( NSString * ) path
modifiers :( NSArray * ) modifiers
state :( BOOL ) state ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseQuery * query = [ self getInternalReferenceForApp : appDisplayName dbURL : dbURL key : key path : path modifiers : modifiers ]. query ;
2017-08-05 21:43:53 +01:00
[ query keepSynced : state ];
2017-08-02 16:51:00 +01:00
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( transactionTryCommit :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
transactionId :( nonnull NSNumber * ) transactionId
updates :( NSDictionary * ) updates ) {
2017-08-02 16:51:00 +01:00
__block NSMutableDictionary * transactionState ;
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
dispatch_sync ( _transactionQueue , ^ {
2018-03-04 23:45:37 +00:00
transactionState = _transactions [[ transactionId stringValue ]];
2017-08-02 16:51:00 +01:00
});
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
if ( ! transactionState ) {
NSLog ( @"tryCommitTransaction for unknown ID %@" , transactionId );
return ;
}
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
dispatch_semaphore_t sema = [ transactionState valueForKey : @"semaphore" ];
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
BOOL abort = [[ updates valueForKey : @"abort" ] boolValue ];
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
if ( abort ) {
[ transactionState setValue :@ true forKey : @"abort" ];
} else {
id newValue = [ updates valueForKey : @"value" ];
[ transactionState setValue : newValue forKey : @"value" ];
}
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
dispatch_semaphore_signal ( sema );
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( transactionStart :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
transactionId :( nonnull NSNumber * ) transactionId
applyLocally :( BOOL ) applyLocally ) {
2017-03-25 00:59:27 +00:00
dispatch_async ( _transactionQueue , ^ {
NSMutableDictionary * transactionState = [ NSMutableDictionary new ];
dispatch_semaphore_t sema = dispatch_semaphore_create ( 0 );
2017-06-16 09:30:02 +01:00
transactionState [ @"semaphore" ] = sema ;
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-05 21:43:53 +01:00
2018-03-04 23:45:37 +00:00
[ ref runTransactionBlock : ^ FIRTransactionResult * _Nonnull ( FIRMutableData * _Nonnull currentData ) {
dispatch_barrier_async ( _transactionQueue , ^ {
[ _transactions setValue : transactionState forKey :[ transactionId stringValue ]];
2017-11-21 15:37:05 -08:00
NSDictionary * updateMap = [ self createTransactionUpdateMap : appDisplayName dbURL : dbURL transactionId : transactionId updatesData : currentData ];
2018-03-04 23:45:37 +00:00
[ RNFirebaseUtil sendJSEvent : self name : DATABASE_TRANSACTION_EVENT body : updateMap ];
});
2017-08-05 21:43:53 +01:00
2018-03-04 23:45:37 +00:00
// wait for the js event handler to call tryCommitTransaction
// this wait occurs on the Firebase Worker Queue
// so if the tryCommitTransaction fails to signal the semaphore
// no further blocks will be executed by Firebase until the timeout expires
dispatch_time_t delayTime = dispatch_time ( DISPATCH_TIME_NOW , 30 * NSEC_PER_SEC );
BOOL timedout = dispatch_semaphore_wait ( sema , delayTime ) != 0 ;
2017-08-05 21:43:53 +01:00
2018-03-04 23:45:37 +00:00
BOOL abort = [ transactionState valueForKey : @"abort" ] || timedout ;
id value = [ transactionState valueForKey : @"value" ];
2017-08-05 21:43:53 +01:00
2018-03-04 23:45:37 +00:00
dispatch_barrier_async ( _transactionQueue , ^ {
[ _transactions removeObjectForKey :[ transactionId stringValue ]];
});
2017-08-05 21:43:53 +01:00
2018-03-04 23:45:37 +00:00
if ( abort ) {
return [ FIRTransactionResult abort ];
} else {
currentData . value = value ;
return [ FIRTransactionResult successWithValue : currentData ];
}
} andCompletionBlock : ^ ( NSError * _Nullable databaseError , BOOL committed , FIRDataSnapshot * _Nullable snapshot ) {
2017-11-21 15:37:05 -08:00
NSDictionary * resultMap = [ self createTransactionResultMap : appDisplayName dbURL : dbURL transactionId : transactionId error : databaseError committed : committed snapshot : snapshot ];
2017-10-26 11:55:07 +01:00
[ RNFirebaseUtil sendJSEvent : self name : DATABASE_TRANSACTION_EVENT body : resultMap ];
2018-03-04 23:45:37 +00:00
} withLocalEvents : applyLocally ];
2017-03-25 00:59:27 +00:00
});
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( onDisconnectSet :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
props :( NSDictionary * ) props
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-02 16:51:00 +01:00
[ ref onDisconnectSetValue : props [ @"value" ] withCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull _ref ) {
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
2017-03-09 15:26:28 +00:00
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( onDisconnectUpdate :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
props :( NSDictionary * ) props
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-02 16:51:00 +01:00
[ ref onDisconnectUpdateChildValues : props withCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull _ref ) {
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
2017-07-19 18:18:16 +01:00
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( onDisconnectRemove :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-02 16:51:00 +01:00
[ ref onDisconnectRemoveValueWithCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull _ref ) {
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
2017-07-19 18:18:16 +01:00
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( onDisconnectCancel :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-02 16:51:00 +01:00
[ ref cancelDisconnectOperationsWithCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull _ref ) {
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
2017-03-09 15:26:28 +00:00
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( set :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
props :( NSDictionary * ) props
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-02 16:51:00 +01:00
[ ref setValue :[ props valueForKey : @"value" ] withCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull _ref ) {
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( setPriority :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
priority :( NSDictionary * ) priority
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-14 11:05:49 +01:00
[ ref setPriority :[ priority valueForKey : @"value" ] withCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull ref ) {
2017-08-02 16:51:00 +01:00
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( setWithPriority :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
data :( NSDictionary * ) data
priority :( NSDictionary * ) priority
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-14 11:05:49 +01:00
[ ref setValue :[ data valueForKey : @"value" ] andPriority :[ priority valueForKey : @"value" ] withCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull ref ) {
2017-08-02 16:51:00 +01:00
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( update :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
props :( NSDictionary * ) props
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-08-02 16:51:00 +01:00
[ ref updateChildValues : props withCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull _ref ) {
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( remove :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
path :( NSString * ) path
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
FIRDatabaseReference * ref = [ self getReferenceForAppPath : appDisplayName dbURL : dbURL path : path ];
2017-05-25 16:00:12 +01:00
[ ref removeValueWithCompletionBlock : ^ ( NSError * _Nullable error , FIRDatabaseReference * _Nonnull _ref ) {
2017-08-02 16:51:00 +01:00
[ RNFirebaseDatabase handlePromise : resolve rejecter : reject databaseError : error ];
2017-03-09 15:26:28 +00:00
}];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( once :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
key :( NSString * ) key
path :( NSString * ) path
modifiers :( NSArray * ) modifiers
eventName :( NSString * ) eventName
resolver :( RCTPromiseResolveBlock ) resolve
rejecter :( RCTPromiseRejectBlock ) reject ) {
2017-11-21 15:37:05 -08:00
RNFirebaseDatabaseReference * ref = [ self getInternalReferenceForApp : appDisplayName dbURL : dbURL key : key path : path modifiers : modifiers ];
2017-08-22 17:29:02 +01:00
[ ref once : eventName resolver : resolve rejecter : reject ];
2017-08-02 16:51:00 +01:00
}
2017-04-26 17:34:16 +01:00
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( on :( NSString * ) appDisplayName
2017-11-21 15:37:05 -08:00
dbURL :( NSString * ) dbURL
2018-03-04 23:45:37 +00:00
props :( NSDictionary * ) props ) {
2017-11-21 15:37:05 -08:00
RNFirebaseDatabaseReference * ref = [ self getCachedInternalReferenceForApp : appDisplayName dbURL : dbURL props : props ];
2017-08-22 17:29:02 +01:00
[ ref on : props [ @"eventType" ] registration : props [ @"registration" ]];
}
2018-03-04 23:45:37 +00:00
RCT_EXPORT_METHOD ( off :( NSString * ) key
eventRegistrationKey :( NSString * ) eventRegistrationKey ) {
2017-08-22 17:29:02 +01:00
RNFirebaseDatabaseReference * ref = _dbReferences [ key ];
2017-10-18 10:29:11 +01:00
if ( ref ) {
[ ref removeEventListener : eventRegistrationKey ];
2017-08-28 13:53:09 +01:00
2017-10-18 10:29:11 +01:00
if ( ! [ ref hasListeners ]) {
[ _dbReferences removeObjectForKey : key ];
}
2017-08-22 17:29:02 +01:00
}
}
2017-08-02 16:51:00 +01:00
/*
* INTERNALS/UTILS
*/
2017-08-14 11:05:49 +01:00
+ ( void ) handlePromise :( RCTPromiseResolveBlock ) resolve rejecter :( RCTPromiseRejectBlock ) reject databaseError :( NSError * ) databaseError {
2017-08-02 16:51:00 +01:00
if ( databaseError != nil ) {
NSDictionary * jsError = [ RNFirebaseDatabase getJSError : databaseError ];
reject ([ jsError valueForKey : @"code" ], [ jsError valueForKey : @"message" ], databaseError );
2017-03-09 15:26:28 +00:00
} else {
2017-08-02 16:51:00 +01:00
resolve ([ NSNull null ]);
2017-03-09 15:26:28 +00:00
}
}
2018-01-03 20:00:38 +00:00
+ ( FIRDatabase * ) getDatabaseForApp :( NSString * ) appDisplayName {
FIRApp * app = [ RNFirebaseUtil getApp : appDisplayName ];
2017-08-02 16:51:00 +01:00
return [ FIRDatabase databaseForApp : app ];
}
2017-03-09 15:26:28 +00:00
2017-11-21 15:37:05 -08:00
+ ( FIRDatabase * ) getDatabaseForApp :( NSString * ) appDisplayName URL :( NSString * ) url {
if ( url == nil ) {
return [ self getDatabaseForApp : appDisplayName ];
}
FIRApp * app = [ RNFirebaseUtil getApp : appDisplayName ];
return [ FIRDatabase databaseForApp : app URL : url ];
2017-08-02 16:51:00 +01:00
}
2017-11-21 15:37:05 -08:00
- ( FIRDatabaseReference * ) getReferenceForAppPath :( NSString * ) appDisplayName dbURL :( NSString * ) dbURL path :( NSString * ) path {
return [[ RNFirebaseDatabase getDatabaseForApp : appDisplayName URL : dbURL ] referenceWithPath : path ];
2017-10-23 17:03:49 +01:00
}
2017-08-05 21:43:53 +01:00
2017-11-21 15:37:05 -08:00
- ( RNFirebaseDatabaseReference * ) getInternalReferenceForApp :( NSString * ) appDisplayName dbURL :( NSString * ) dbURL key :( NSString * ) key path :( NSString * ) path modifiers :( NSArray * ) modifiers {
return [[ RNFirebaseDatabaseReference alloc ] initWithPathAndModifiers : self appDisplayName : appDisplayName dbURL : dbURL key : key refPath : path modifiers : modifiers ];
}
- ( RNFirebaseDatabaseReference * ) getCachedInternalReferenceForApp :( NSString * ) appDisplayName dbURL :( NSString * ) dbURL props :( NSDictionary * ) props {
2017-10-23 17:03:49 +01:00
NSString * key = props [ @"key" ];
NSString * path = props [ @"path" ];
2017-11-21 15:37:05 -08:00
NSArray * modifiers = props [ @"modifiers" ];
2017-10-26 11:55:07 +01:00
2017-10-23 17:03:49 +01:00
RNFirebaseDatabaseReference * ref = _dbReferences [ key ];
2017-10-26 11:55:07 +01:00
2017-08-02 16:51:00 +01:00
if ( ref == nil ) {
2017-11-21 15:37:05 -08:00
ref = [[ RNFirebaseDatabaseReference alloc ] initWithPathAndModifiers : self appDisplayName : appDisplayName dbURL : dbURL key : key refPath : path modifiers : modifiers ];
2017-10-23 17:03:49 +01:00
_dbReferences [ key ] = ref ;
2017-08-02 16:51:00 +01:00
}
return ref ;
}
// TODO: Move to error util for use in other modules
2017-08-14 11:05:49 +01:00
+ ( NSString * ) getMessageWithService :( NSString * ) message service :( NSString * ) service fullCode :( NSString * ) fullCode {
2017-08-02 16:51:00 +01:00
return [ NSString stringWithFormat : @"%@: %@ (%@)." , service , message , [ fullCode lowercaseString ]];
}
2017-08-14 11:05:49 +01:00
+ ( NSString * ) getCodeWithService :( NSString * ) service code :( NSString * ) code {
2017-08-28 13:53:09 +01:00
return [ NSString stringWithFormat : @"%@/%@" , [ service lowercaseString ], [ code lowercaseString ]];
2017-08-02 16:51:00 +01:00
}
2017-08-14 11:05:49 +01:00
+ ( NSDictionary * ) getJSError :( NSError * ) nativeError {
2017-08-02 16:51:00 +01:00
NSMutableDictionary * errorMap = [[ NSMutableDictionary alloc ] init ];
[ errorMap setValue : @( nativeError . code ) forKey : @"nativeErrorCode" ];
[ errorMap setValue :[ nativeError localizedDescription ] forKey : @"nativeErrorMessage" ];
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
NSString * code ;
NSString * message ;
NSString * service = @"Database" ;
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
switch ( nativeError . code ) {
// iOS confirmed codes
case 1 : // -3 on Android
code = [ RNFirebaseDatabase getCodeWithService : service code : @"permission-denied" ];
message = [ RNFirebaseDatabase getMessageWithService : @"Client doesn't have permission to access the desired data." service : service fullCode : code ];
break ;
case 2 : // -10 on Android
code = [ RNFirebaseDatabase getCodeWithService : service code : @"unavailable" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The service is unavailable." service : service fullCode : code ];
break ;
case 3 : // -25 on Android
code = [ RNFirebaseDatabase getCodeWithService : service code : @"write-cancelled" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The write was canceled by the user." service : service fullCode : code ];
break ;
2018-03-04 23:45:37 +00:00
// TODO: Missing iOS equivalent codes
2017-08-02 16:51:00 +01:00
case - 1 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"data-stale" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The transaction needs to be run again with current data." service : service fullCode : code ];
break ;
case - 2 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"failure" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The server indicated that this operation failed." service : service fullCode : code ];
break ;
case - 4 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"disconnected" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The operation had to be aborted due to a network disconnect." service : service fullCode : code ];
break ;
case - 6 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"expired-token" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The supplied auth token has expired." service : service fullCode : code ];
break ;
case - 7 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"invalid-token" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The supplied auth token was invalid." service : service fullCode : code ];
break ;
case - 8 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"max-retries" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The transaction had too many retries." service : service fullCode : code ];
break ;
case - 9 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"overridden-by-set" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The transaction was overridden by a subsequent set." service : service fullCode : code ];
break ;
case - 11 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"user-code-exception" ];
message = [ RNFirebaseDatabase getMessageWithService : @"User code called from the Firebase Database runloop threw an exception." service : service fullCode : code ];
break ;
case - 24 :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"network-error" ];
message = [ RNFirebaseDatabase getMessageWithService : @"The operation could not be performed due to a network error." service : service fullCode : code ];
break ;
default :
code = [ RNFirebaseDatabase getCodeWithService : service code : @"unknown" ];
message = [ RNFirebaseDatabase getMessageWithService : @"An unknown error occurred." service : service fullCode : code ];
break ;
}
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
[ errorMap setValue : code forKey : @"code" ];
[ errorMap setValue : message forKey : @"message" ];
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
return errorMap ;
}
2017-11-21 15:37:05 -08:00
- ( NSDictionary * ) createTransactionUpdateMap :( NSString * ) appDisplayName dbURL :( NSString * ) dbURL transactionId :( NSNumber * ) transactionId updatesData :( FIRMutableData * ) updatesData {
2017-08-02 16:51:00 +01:00
NSMutableDictionary * updatesMap = [[ NSMutableDictionary alloc ] init ];
[ updatesMap setValue : transactionId forKey : @"id" ];
[ updatesMap setValue : @"update" forKey : @"type" ];
2018-01-03 20:00:38 +00:00
[ updatesMap setValue : appDisplayName forKey : @"appName" ];
2017-11-21 15:37:05 -08:00
[ updatesMap setValue : dbURL forKey : @"dbURL" ];
2017-08-02 16:51:00 +01:00
[ updatesMap setValue : updatesData . value forKey : @"value" ];
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
return updatesMap ;
}
2017-11-21 15:37:05 -08:00
- ( NSDictionary * ) createTransactionResultMap :( NSString * ) appDisplayName dbURL :( NSString * ) dbURL transactionId :( NSNumber * ) transactionId error :( NSError * ) error committed :( BOOL ) committed snapshot :( FIRDataSnapshot * ) snapshot {
2017-08-02 16:51:00 +01:00
NSMutableDictionary * resultMap = [[ NSMutableDictionary alloc ] init ];
[ resultMap setValue : transactionId forKey : @"id" ];
2018-01-03 20:00:38 +00:00
[ resultMap setValue : appDisplayName forKey : @"appName" ];
2017-11-21 15:37:05 -08:00
[ resultMap setValue : dbURL forKey : @"dbURL" ];
2017-08-02 16:51:00 +01:00
// TODO: no timeout on iOS
[ resultMap setValue : @( committed ) forKey : @"committed" ];
// TODO: no interrupted on iOS
if ( error != nil ) {
[ resultMap setValue : @"error" forKey : @"type" ];
[ resultMap setValue :[ RNFirebaseDatabase getJSError : error ] forKey : @"error" ];
// TODO: timeout error on iOS
} else {
[ resultMap setValue : @"complete" forKey : @"type" ];
[ resultMap setValue :[ RNFirebaseDatabaseReference snapshotToDict : snapshot ] forKey : @"snapshot" ];
}
2017-08-05 21:43:53 +01:00
2017-08-02 16:51:00 +01:00
return resultMap ;
}
2017-03-09 15:26:28 +00:00
- ( NSArray < NSString *> * ) supportedEvents {
2017-08-16 21:39:05 +01:00
return @[ DATABASE_SYNC_EVENT , DATABASE_TRANSACTION_EVENT ] ;
2017-03-09 15:26:28 +00:00
}
2018-03-04 23:45:37 +00:00
+ ( BOOL ) requiresMainQueueSetup {
2017-10-12 09:18:01 +01:00
return YES ;
}
2017-03-09 15:26:28 +00:00
@end
2017-05-25 16:00:12 +01:00
#else
@implementation RNFirebaseDatabase
@end
#endif