2017-09-28 12:48:28 +00:00
# import "RNFirebaseFirestore.h"
2017-10-03 16:23:28 +00:00
# if __has _include ( < FirebaseFirestore / FirebaseFirestore . h > )
2017-09-28 12:48:28 +00:00
# import < Firebase . h >
# import "RNFirebaseEvents.h"
# import "RNFirebaseFirestoreCollectionReference.h"
# import "RNFirebaseFirestoreDocumentReference.h"
@ implementation RNFirebaseFirestore
RCT_EXPORT _MODULE ( ) ;
- ( id ) init {
self = [ super init ] ;
if ( self ! = nil ) {
2017-10-03 16:23:28 +00:00
2017-09-28 12:48:28 +00:00
}
return self ;
}
RCT_EXPORT _METHOD ( collectionGet : ( NSString * ) appName
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 ] ;
}
2017-10-03 09:12:25 +00:00
RCT_EXPORT _METHOD ( collectionOffSnapshot : ( NSString * ) appName
path : ( NSString * ) path
filters : ( NSArray * ) filters
orders : ( NSArray * ) orders
options : ( NSDictionary * ) options
listenerId : ( nonnull NSString * ) listenerId ) {
[ RNFirebaseFirestoreCollectionReference offSnapshot : listenerId ] ;
}
RCT_EXPORT _METHOD ( collectionOnSnapshot : ( NSString * ) appName
path : ( NSString * ) path
filters : ( NSArray * ) filters
orders : ( NSArray * ) orders
options : ( NSDictionary * ) options
2017-10-06 11:00:40 +00:00
listenerId : ( nonnull NSString * ) listenerId
queryListenOptions : ( NSDictionary * ) queryListenOptions ) {
2017-10-03 09:12:25 +00:00
RNFirebaseFirestoreCollectionReference * ref = [ self getCollectionForAppPath : appName path : path filters : filters orders : orders options : options ] ;
2017-10-06 11:00:40 +00:00
[ ref onSnapshot : listenerId queryListenOptions : queryListenOptions ] ;
2017-10-03 09:12:25 +00:00
}
2017-09-28 12:48:28 +00:00
RCT_EXPORT _METHOD ( documentBatch : ( NSString * ) appName
writes : ( NSArray * ) writes
resolver : ( RCTPromiseResolveBlock ) resolve
rejecter : ( RCTPromiseRejectBlock ) reject ) {
FIRFirestore * firestore = [ RNFirebaseFirestore getFirestoreForApp : appName ] ;
FIRWriteBatch * batch = [ firestore batch ] ;
2017-10-03 16:23:28 +00:00
2017-09-28 12:48:28 +00:00
for ( NSDictionary * write in writes ) {
NSString * type = write [ @ "type" ] ;
NSString * path = write [ @ "path" ] ;
2017-10-10 16:22:12 +00:00
NSDictionary * data = [ RNFirebaseFirestoreDocumentReference parseJSMap : firestore jsMap : write [ @ "data" ] ] ;
2017-10-03 16:23:28 +00:00
2017-09-28 12:48:28 +00:00
FIRDocumentReference * ref = [ firestore documentWithPath : path ] ;
2017-10-03 16:23:28 +00:00
2017-09-28 12:48:28 +00:00
if ( [ type isEqualToString : @ "DELETE" ] ) {
batch = [ batch deleteDocument : ref ] ;
} else if ( [ type isEqualToString : @ "SET" ] ) {
NSDictionary * options = write [ @ "options" ] ;
if ( options && options [ @ "merge" ] ) {
batch = [ batch setData : data forDocument : ref options : [ FIRSetOptions merge ] ] ;
} else {
batch = [ batch setData : data forDocument : ref ] ;
}
} else if ( [ type isEqualToString : @ "UPDATE" ] ) {
batch = [ batch updateData : data forDocument : ref ] ;
}
}
[ batch commitWithCompletion : ^ ( NSError * _Nullable error ) {
if ( error ) {
[ RNFirebaseFirestore promiseRejectException : reject error : error ] ;
} else {
2017-10-05 09:18:24 +00:00
resolve ( nil ) ;
2017-09-28 12:48:28 +00:00
}
} ] ;
}
RCT_EXPORT _METHOD ( documentDelete : ( NSString * ) appName
path : ( NSString * ) path
resolver : ( RCTPromiseResolveBlock ) resolve
rejecter : ( RCTPromiseRejectBlock ) reject ) {
2017-10-05 09:18:24 +00:00
[ [ self getDocumentForAppPath : appName path : path ] delete : resolve rejecter : reject ] ;
2017-09-28 12:48:28 +00:00
}
RCT_EXPORT _METHOD ( documentGet : ( NSString * ) appName
path : ( NSString * ) path
resolver : ( RCTPromiseResolveBlock ) resolve
rejecter : ( RCTPromiseRejectBlock ) reject ) {
[ [ self getDocumentForAppPath : appName path : path ] get : resolve rejecter : reject ] ;
}
RCT_EXPORT _METHOD ( documentGetAll : ( NSString * ) appName
documents : ( NSString * ) documents
resolver : ( RCTPromiseResolveBlock ) resolve
rejecter : ( RCTPromiseRejectBlock ) reject ) {
// Not supported on iOS out of the box
}
2017-10-02 14:45:07 +00:00
RCT_EXPORT _METHOD ( documentOffSnapshot : ( NSString * ) appName
path : ( NSString * ) path
2017-10-03 09:12:25 +00:00
listenerId : ( nonnull NSString * ) listenerId ) {
[ RNFirebaseFirestoreDocumentReference offSnapshot : listenerId ] ;
2017-10-02 14:45:07 +00:00
}
RCT_EXPORT _METHOD ( documentOnSnapshot : ( NSString * ) appName
path : ( NSString * ) path
2017-10-06 11:00:40 +00:00
listenerId : ( nonnull NSString * ) listenerId
docListenOptions : ( NSDictionary * ) docListenOptions ) {
2017-10-03 09:12:25 +00:00
RNFirebaseFirestoreDocumentReference * ref = [ self getDocumentForAppPath : appName path : path ] ;
2017-10-06 11:00:40 +00:00
[ ref onSnapshot : listenerId docListenOptions : docListenOptions ] ;
2017-10-02 14:45:07 +00:00
}
2017-09-28 12:48:28 +00:00
RCT_EXPORT _METHOD ( documentSet : ( NSString * ) appName
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 ] ;
}
RCT_EXPORT _METHOD ( documentUpdate : ( NSString * ) appName
path : ( NSString * ) path
data : ( NSDictionary * ) data
resolver : ( RCTPromiseResolveBlock ) resolve
rejecter : ( RCTPromiseRejectBlock ) reject ) {
[ [ self getDocumentForAppPath : appName path : path ] update : data resolver : resolve rejecter : reject ] ;
}
/ *
* INTERNALS / UTILS
* /
+ ( void ) promiseRejectException : ( RCTPromiseRejectBlock ) reject error : ( NSError * ) error {
2017-10-02 14:45:07 +00:00
NSDictionary * jsError = [ RNFirebaseFirestore getJSError : error ] ;
reject ( [ jsError valueForKey : @ "code" ] , [ jsError valueForKey : @ "message" ] , error ) ;
2017-09-28 12:48:28 +00:00
}
+ ( FIRFirestore * ) getFirestoreForApp : ( NSString * ) appName {
FIRApp * app = [ FIRApp appNamed : appName ] ;
return [ FIRFirestore firestoreForApp : app ] ;
}
- ( RNFirebaseFirestoreCollectionReference * ) getCollectionForAppPath : ( NSString * ) appName path : ( NSString * ) path filters : ( NSArray * ) filters orders : ( NSArray * ) orders options : ( NSDictionary * ) options {
2017-10-03 09:12:25 +00:00
return [ [ RNFirebaseFirestoreCollectionReference alloc ] initWithPathAndModifiers : self app : appName path : path filters : filters orders : orders options : options ] ;
2017-10-02 14:45:07 +00:00
}
2017-09-28 12:48:28 +00:00
- ( RNFirebaseFirestoreDocumentReference * ) getDocumentForAppPath : ( NSString * ) appName path : ( NSString * ) path {
2017-10-02 14:45:07 +00:00
return [ [ RNFirebaseFirestoreDocumentReference alloc ] initWithPath : self app : appName path : path ] ;
}
// TODO : Move to error util for use in other modules
+ ( NSString * ) getMessageWithService : ( NSString * ) message service : ( NSString * ) service fullCode : ( NSString * ) fullCode {
return [ NSString stringWithFormat : @ "%@: %@ (%@)." , service , message , [ fullCode lowercaseString ] ] ;
}
+ ( NSString * ) getCodeWithService : ( NSString * ) service code : ( NSString * ) code {
return [ NSString stringWithFormat : @ "%@/%@" , [ service lowercaseString ] , [ code lowercaseString ] ] ;
}
+ ( NSDictionary * ) getJSError : ( NSError * ) nativeError {
NSMutableDictionary * errorMap = [ [ NSMutableDictionary alloc ] init ] ;
[ errorMap setValue : @ ( nativeError . code ) forKey : @ "nativeErrorCode" ] ;
[ errorMap setValue : [ nativeError localizedDescription ] forKey : @ "nativeErrorMessage" ] ;
2017-10-03 16:23:28 +00:00
2017-10-02 14:45:07 +00:00
NSString * code ;
NSString * message ;
NSString * service = @ "Firestore" ;
2017-10-03 16:23:28 +00:00
2017-10-02 14:45:07 +00:00
switch ( nativeError . code ) {
2017-10-05 09:32:14 +00:00
case FIRFirestoreErrorCodeOK :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "ok" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Ok." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeCancelled :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "cancelled" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "The operation was cancelled." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeUnknown :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "unknown" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Unknown error or an error from a different error domain." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeInvalidArgument :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "invalid-argument" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Client specified an invalid argument." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeDeadlineExceeded :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "deadline-exceeded" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Deadline expired before operation could complete." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeNotFound :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "not-found" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Some requested document was not found." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeAlreadyExists :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "already-exists" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Some document that we attempted to create already exists." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodePermissionDenied :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "permission-denied" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "The caller does not have permission to execute the specified operation." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeResourceExhausted :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "resource-exhausted" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeFailedPrecondition :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "failed-precondition" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Operation was rejected because the system is not in a state required for the operation`s execution." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeAborted :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "aborted" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "The operation was aborted, typically due to a concurrency issue like transaction aborts, etc." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeOutOfRange :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "out-of-range" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Operation was attempted past the valid range." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeUnimplemented :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "unimplemented" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Operation is not implemented or not supported/enabled." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeInternal :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "internal" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Internal errors." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeUnavailable :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "unavailable" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "The service is currently unavailable." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeDataLoss :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "data-loss" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "Unrecoverable data loss or corruption." service : service fullCode : code ] ;
break ;
case FIRFirestoreErrorCodeUnauthenticated :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "unauthenticated" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "The request does not have valid authentication credentials for the operation." service : service fullCode : code ] ;
break ;
2017-10-02 14:45:07 +00:00
default :
code = [ RNFirebaseFirestore getCodeWithService : service code : @ "unknown" ] ;
message = [ RNFirebaseFirestore getMessageWithService : @ "An unknown error occurred." service : service fullCode : code ] ;
break ;
}
2017-10-03 16:23:28 +00:00
2017-10-02 14:45:07 +00:00
[ errorMap setValue : code forKey : @ "code" ] ;
[ errorMap setValue : message forKey : @ "message" ] ;
2017-10-03 16:23:28 +00:00
2017-10-02 14:45:07 +00:00
return errorMap ;
2017-09-28 12:48:28 +00:00
}
- ( NSArray < NSString * > * ) supportedEvents {
2017-10-02 14:45:07 +00:00
return @ [ FIRESTORE_COLLECTION _SYNC _EVENT , FIRESTORE_DOCUMENT _SYNC _EVENT ] ;
2017-09-28 12:48:28 +00:00
}
2017-10-12 08:18:01 +00:00
+ ( BOOL ) requiresMainQueueSetup
{
return YES ;
}
2017-09-28 12:48:28 +00:00
@ end
# else
@ implementation RNFirebaseFirestore
@ end
# endif