[firestore][ios] Add initial iOS functionality

This commit is contained in:
Chris Bianca 2017-09-28 13:48:28 +01:00
parent f56435226d
commit 6060c36c1c
12 changed files with 682 additions and 16 deletions

View File

@ -12,6 +12,9 @@
8323CF071F6FBD870071420B /* NativeExpressComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF011F6FBD870071420B /* NativeExpressComponent.m */; }; 8323CF071F6FBD870071420B /* NativeExpressComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF011F6FBD870071420B /* NativeExpressComponent.m */; };
8323CF081F6FBD870071420B /* RNFirebaseAdMobBannerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF031F6FBD870071420B /* RNFirebaseAdMobBannerManager.m */; }; 8323CF081F6FBD870071420B /* RNFirebaseAdMobBannerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF031F6FBD870071420B /* RNFirebaseAdMobBannerManager.m */; };
8323CF091F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF051F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m */; }; 8323CF091F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF051F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m */; };
8376F7141F7C149100D45A85 /* RNFirebaseFirestoreDocumentReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F70E1F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.m */; };
8376F7151F7C149100D45A85 /* RNFirebaseFirestore.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F7101F7C149000D45A85 /* RNFirebaseFirestore.m */; };
8376F7161F7C149100D45A85 /* RNFirebaseFirestoreCollectionReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F7111F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.m */; };
839D916C1EF3E20B0077C7C8 /* RNFirebaseAdMob.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D914F1EF3E20A0077C7C8 /* RNFirebaseAdMob.m */; }; 839D916C1EF3E20B0077C7C8 /* RNFirebaseAdMob.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D914F1EF3E20A0077C7C8 /* RNFirebaseAdMob.m */; };
839D916D1EF3E20B0077C7C8 /* RNFirebaseAdMobInterstitial.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91511EF3E20A0077C7C8 /* RNFirebaseAdMobInterstitial.m */; }; 839D916D1EF3E20B0077C7C8 /* RNFirebaseAdMobInterstitial.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91511EF3E20A0077C7C8 /* RNFirebaseAdMobInterstitial.m */; };
839D916E1EF3E20B0077C7C8 /* RNFirebaseAdMobRewardedVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91531EF3E20A0077C7C8 /* RNFirebaseAdMobRewardedVideo.m */; }; 839D916E1EF3E20B0077C7C8 /* RNFirebaseAdMobRewardedVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 839D91531EF3E20A0077C7C8 /* RNFirebaseAdMobRewardedVideo.m */; };
@ -50,6 +53,12 @@
8323CF031F6FBD870071420B /* RNFirebaseAdMobBannerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMobBannerManager.m; sourceTree = "<group>"; }; 8323CF031F6FBD870071420B /* RNFirebaseAdMobBannerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMobBannerManager.m; sourceTree = "<group>"; };
8323CF041F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMobNativeExpressManager.h; sourceTree = "<group>"; }; 8323CF041F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMobNativeExpressManager.h; sourceTree = "<group>"; };
8323CF051F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMobNativeExpressManager.m; sourceTree = "<group>"; }; 8323CF051F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMobNativeExpressManager.m; sourceTree = "<group>"; };
8376F70E1F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseFirestoreDocumentReference.m; sourceTree = "<group>"; };
8376F70F1F7C149000D45A85 /* RNFirebaseFirestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseFirestore.h; sourceTree = "<group>"; };
8376F7101F7C149000D45A85 /* RNFirebaseFirestore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseFirestore.m; sourceTree = "<group>"; };
8376F7111F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseFirestoreCollectionReference.m; sourceTree = "<group>"; };
8376F7121F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseFirestoreDocumentReference.h; sourceTree = "<group>"; };
8376F7131F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseFirestoreCollectionReference.h; sourceTree = "<group>"; };
839D914E1EF3E20A0077C7C8 /* RNFirebaseAdMob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMob.h; sourceTree = "<group>"; }; 839D914E1EF3E20A0077C7C8 /* RNFirebaseAdMob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMob.h; sourceTree = "<group>"; };
839D914F1EF3E20A0077C7C8 /* RNFirebaseAdMob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMob.m; sourceTree = "<group>"; }; 839D914F1EF3E20A0077C7C8 /* RNFirebaseAdMob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMob.m; sourceTree = "<group>"; };
839D91501EF3E20A0077C7C8 /* RNFirebaseAdMobInterstitial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMobInterstitial.h; sourceTree = "<group>"; }; 839D91501EF3E20A0077C7C8 /* RNFirebaseAdMobInterstitial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMobInterstitial.h; sourceTree = "<group>"; };
@ -105,6 +114,7 @@
839D915A1EF3E20A0077C7C8 /* config */, 839D915A1EF3E20A0077C7C8 /* config */,
839D915D1EF3E20A0077C7C8 /* crash */, 839D915D1EF3E20A0077C7C8 /* crash */,
839D91601EF3E20A0077C7C8 /* database */, 839D91601EF3E20A0077C7C8 /* database */,
8376F70D1F7C141500D45A85 /* firestore */,
839D91631EF3E20A0077C7C8 /* messaging */, 839D91631EF3E20A0077C7C8 /* messaging */,
839D91661EF3E20A0077C7C8 /* perf */, 839D91661EF3E20A0077C7C8 /* perf */,
839D91691EF3E20A0077C7C8 /* storage */, 839D91691EF3E20A0077C7C8 /* storage */,
@ -115,6 +125,20 @@
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
8376F70D1F7C141500D45A85 /* firestore */ = {
isa = PBXGroup;
children = (
8376F70F1F7C149000D45A85 /* RNFirebaseFirestore.h */,
8376F7101F7C149000D45A85 /* RNFirebaseFirestore.m */,
8376F7131F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.h */,
8376F7111F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.m */,
8376F7121F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.h */,
8376F70E1F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.m */,
);
name = firestore;
path = RNFirebase/firestore;
sourceTree = "<group>";
};
839D914D1EF3E20A0077C7C8 /* admob */ = { 839D914D1EF3E20A0077C7C8 /* admob */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -277,9 +301,12 @@
files = ( files = (
839D916E1EF3E20B0077C7C8 /* RNFirebaseAdMobRewardedVideo.m in Sources */, 839D916E1EF3E20B0077C7C8 /* RNFirebaseAdMobRewardedVideo.m in Sources */,
839D916C1EF3E20B0077C7C8 /* RNFirebaseAdMob.m in Sources */, 839D916C1EF3E20B0077C7C8 /* RNFirebaseAdMob.m in Sources */,
8376F7161F7C149100D45A85 /* RNFirebaseFirestoreCollectionReference.m in Sources */,
839D91761EF3E20B0077C7C8 /* RNFirebaseStorage.m in Sources */, 839D91761EF3E20B0077C7C8 /* RNFirebaseStorage.m in Sources */,
8376F7151F7C149100D45A85 /* RNFirebaseFirestore.m in Sources */,
839D91701EF3E20B0077C7C8 /* RNFirebaseAuth.m in Sources */, 839D91701EF3E20B0077C7C8 /* RNFirebaseAuth.m in Sources */,
8323CF091F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m in Sources */, 8323CF091F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m in Sources */,
8376F7141F7C149100D45A85 /* RNFirebaseFirestoreDocumentReference.m in Sources */,
839D916F1EF3E20B0077C7C8 /* RNFirebaseAnalytics.m in Sources */, 839D916F1EF3E20B0077C7C8 /* RNFirebaseAnalytics.m in Sources */,
839D91711EF3E20B0077C7C8 /* RNFirebaseRemoteConfig.m in Sources */, 839D91711EF3E20B0077C7C8 /* RNFirebaseRemoteConfig.m in Sources */,
D950369E1D19C77400F7094D /* RNFirebase.m in Sources */, D950369E1D19C77400F7094D /* RNFirebase.m in Sources */,

View File

@ -0,0 +1,26 @@
#ifndef RNFirebaseFirestore_h
#define RNFirebaseFirestore_h
#import <Foundation/Foundation.h>
#if __has_include(<Firestore/FIRFirestore.h>)
#import <Firestore/FIRFirestore.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface RNFirebaseFirestore : RCTEventEmitter <RCTBridgeModule> {}
+ (void)promiseRejectException:(RCTPromiseRejectBlock)reject error:(NSError *)error;
+ (FIRFirestore *)getFirestoreForApp:(NSString *)appName;
@end
#else
@interface RNFirebaseFirestore : NSObject
@end
#endif
#endif

View File

@ -0,0 +1,162 @@
#import "RNFirebaseFirestore.h"
#if __has_include(<Firestore/FIRFirestore.h>)
#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) {
}
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];
}
RCT_EXPORT_METHOD(documentBatch:(NSString *) appName
writes:(NSArray *) writes
commitOptions:(NSDictionary *) commitOptions
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) {
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appName];
FIRWriteBatch *batch = [firestore batch];
for (NSDictionary *write in writes) {
NSString *type = write[@"type"];
NSString *path = write[@"path"];
NSDictionary *data = write[@"data"];
FIRDocumentReference *ref = [firestore documentWithPath:path];
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 {
NSMutableArray *result = [[NSMutableArray alloc] init];
for (NSDictionary *write in writes) {
// Missing fields from web SDK
// writeTime
[result addObject:@{}];
}
resolve(result);
}
}];
}
RCT_EXPORT_METHOD(documentCollections:(NSString *) appName
path:(NSString *) path
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) {
[[self getDocumentForAppPath:appName path:path] get:resolve rejecter:reject];
}
RCT_EXPORT_METHOD(documentCreate:(NSString *) appName
path:(NSString *) path
data:(NSDictionary *) data
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) {
[[self getDocumentForAppPath:appName path:path] create:data resolver:resolve rejecter:reject];
}
RCT_EXPORT_METHOD(documentDelete:(NSString *) appName
path:(NSString *) path
options:(NSDictionary *) options
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) {
[[self getDocumentForAppPath:appName path:path] delete:options resolver:resolve rejecter:reject];
}
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
}
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 {
// TODO
// NSDictionary *jsError = [RNFirebaseDatabase getJSError:databaseError];
// reject([jsError valueForKey:@"code"], [jsError valueForKey:@"message"], databaseError);
reject(@"TODO", [error description], error);
}
+ (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 {
return [[RNFirebaseFirestoreCollectionReference alloc] initWithPathAndModifiers:appName path:path filters:filters orders:orders options:options];
}
- (RNFirebaseFirestoreDocumentReference *)getDocumentForAppPath:(NSString *)appName path:(NSString *)path {
return [[RNFirebaseFirestoreDocumentReference alloc] initWithPath:appName path:path];
}
- (NSArray<NSString *> *)supportedEvents {
return @[DATABASE_SYNC_EVENT, DATABASE_TRANSACTION_EVENT];
}
@end
#else
@implementation RNFirebaseFirestore
@end
#endif

View File

@ -0,0 +1,30 @@
#ifndef RNFirebaseFirestoreCollectionReference_h
#define RNFirebaseFirestoreCollectionReference_h
#import <Foundation/Foundation.h>
#if __has_include(<Firestore/FIRFirestore.h>)
#import <Firestore/Firestore.h>
#import "RNFirebaseFirestore.h"
#import "RNFirebaseFirestoreDocumentReference.h"
@interface RNFirebaseFirestoreCollectionReference : NSObject
@property NSString *app;
@property NSString *path;
@property NSArray *filters;
@property NSArray *orders;
@property NSDictionary *options;
@property FIRQuery *query;
- (id)initWithPathAndModifiers:(NSString *)app path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options;
- (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
+ (NSDictionary *)snapshotToDictionary:(FIRQuerySnapshot *)querySnapshot;
@end
#else
@interface RNFirebaseFirestoreCollectionReference : NSObject
@end
#endif
#endif

View File

@ -0,0 +1,145 @@
#import "RNFirebaseFirestoreCollectionReference.h"
@implementation RNFirebaseFirestoreCollectionReference
#if __has_include(<Firestore/FIRFirestore.h>)
- (id)initWithPathAndModifiers:(NSString *) app
path:(NSString *) path
filters:(NSArray *) filters
orders:(NSArray *) orders
options:(NSDictionary *) options {
self = [super init];
if (self) {
_app = app;
_path = path;
_filters = filters;
_orders = orders;
_options = options;
_query = [self buildQuery];
}
return self;
}
- (void)get:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
[_query getDocumentsWithCompletion:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) {
if (error) {
[RNFirebaseFirestore promiseRejectException:reject error:error];
} else {
NSDictionary *data = [RNFirebaseFirestoreCollectionReference snapshotToDictionary:snapshot];
resolve(data);
}
}];
}
- (FIRQuery *)buildQuery {
FIRQuery *query = (FIRQuery*)[[RNFirebaseFirestore getFirestoreForApp:_app] collectionWithPath:_path];
query = [self applyFilters:query];
query = [self applyOrders:query];
query = [self applyOptions:query];
return query;
}
- (FIRQuery *)applyFilters:(FIRQuery *) query {
for (NSDictionary *filter in _filters) {
NSString *fieldPath = filter[@"fieldPath"];
NSString *operator = filter[@"operator"];
// TODO: Validate this works
id value = filter[@"value"];
if ([operator isEqualToString:@"EQUAL"]) {
query = [query queryWhereField:fieldPath isEqualTo:value];
} else if ([operator isEqualToString:@"GREATER_THAN"]) {
query = [query queryWhereField:fieldPath isGreaterThan:value];
} else if ([operator isEqualToString:@"GREATER_THAN_OR_EQUAL"]) {
query = [query queryWhereField:fieldPath isGreaterThanOrEqualTo:value];
} else if ([operator isEqualToString:@"LESS_THAN"]) {
query = [query queryWhereField:fieldPath isLessThan:value];
} else if ([operator isEqualToString:@"LESS_THAN_OR_EQUAL"]) {
query = [query queryWhereField:fieldPath isLessThanOrEqualTo:value];
}
}
return query;
}
- (FIRQuery *)applyOrders:(FIRQuery *) query {
for (NSDictionary *order in _orders) {
NSString *direction = order[@"direction"];
NSString *fieldPath = order[@"fieldPath"];
query = [query queryOrderedByField:fieldPath descending:([direction isEqualToString:@"DESCENDING"])];
}
return query;
}
- (FIRQuery *)applyOptions:(FIRQuery *) query {
if (_options[@"endAt"]) {
query = [query queryEndingAtValues:_options[@"endAt"]];
}
if (_options[@"endBefore"]) {
query = [query queryEndingBeforeValues:_options[@"endBefore"]];
}
if (_options[@"offset"]) {
// iOS doesn't support offset
}
if (_options[@"selectFields"]) {
// iOS doesn't support selectFields
}
if (_options[@"startAfter"]) {
query = [query queryStartingAfterValues:_options[@"startAfter"]];
}
if (_options[@"startAt"]) {
query = [query queryStartingAtValues:_options[@"startAt"]];
}
return query;
}
+ (NSDictionary *)snapshotToDictionary:(FIRQuerySnapshot *)querySnapshot {
NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init];
[snapshot setValue:[self documentChangesToArray:querySnapshot.documentChanges] forKey:@"changes"];
[snapshot setValue:[self documentSnapshotsToArray:querySnapshot.documents] forKey:@"documents"];
return snapshot;
}
+ (NSArray *)documentChangesToArray:(NSArray<FIRDocumentChange *> *) documentChanges {
NSMutableArray *changes = [[NSMutableArray alloc] init];
for (FIRDocumentChange *change in documentChanges) {
[changes addObject:[self documentChangeToDictionary:change]];
}
return changes;
}
+ (NSDictionary *)documentChangeToDictionary:(FIRDocumentChange *)documentChange {
NSMutableDictionary *change = [[NSMutableDictionary alloc] init];
[change setValue:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:documentChange.document] forKey:@"document"];
[change setValue:@(documentChange.newIndex) forKey:@"newIndex"];
[change setValue:@(documentChange.oldIndex) forKey:@"oldIndex"];
if (documentChange.type == FIRDocumentChangeTypeAdded) {
[change setValue:@"added" forKey:@"type"];
} else if (documentChange.type == FIRDocumentChangeTypeRemoved) {
[change setValue:@"removed" forKey:@"type"];
} else if (documentChange.type == FIRDocumentChangeTypeModified) {
[change setValue:@"modified" forKey:@"type"];
}
return change;
}
+ (NSArray *)documentSnapshotsToArray:(NSArray<FIRDocumentSnapshot *> *) documentSnapshots {
NSMutableArray *snapshots = [[NSMutableArray alloc] init];
for (FIRDocumentSnapshot *snapshot in documentSnapshots) {
[snapshots addObject:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:snapshot]];
}
return snapshots;
}
#endif
@end

View File

@ -0,0 +1,32 @@
#ifndef RNFirebaseFirestoreDocumentReference_h
#define RNFirebaseFirestoreDocumentReference_h
#import <Foundation/Foundation.h>
#if __has_include(<Firestore/FIRFirestore.h>)
#import <Firestore/Firestore.h>
#import "RNFirebaseFirestore.h"
@interface RNFirebaseFirestoreDocumentReference : NSObject
@property NSString *app;
@property NSString *path;
@property FIRDocumentReference *ref;
- (id)initWithPath:(NSString *)app path:(NSString *)path;
- (void)collections:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)create:(NSDictionary *)data resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)delete:(NSDictionary *)options resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)set:(NSDictionary *)data options:(NSDictionary *)options resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)update:(NSDictionary *)data resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
+ (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot;
@end
#else
@interface RNFirebaseFirestoreDocumentReference : NSObject
@end
#endif
#endif

View File

@ -0,0 +1,100 @@
#import "RNFirebaseFirestoreDocumentReference.h"
@implementation RNFirebaseFirestoreDocumentReference
#if __has_include(<Firestore/FIRFirestore.h>)
- (id)initWithPath:(NSString *) app
path:(NSString *) path {
self = [super init];
if (self) {
_app = app;
_path = path;
_ref = [[RNFirebaseFirestore getFirestoreForApp:_app] documentWithPath:_path];
}
return self;
}
- (void)collections:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
// Not supported on iOS
}
- (void)create:(NSDictionary *) data
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
// Not supported on iOS out of the box
}
- (void)delete:(NSDictionary *)options
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
[_ref deleteDocumentWithCompletion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}];
}
- (void)get:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
[_ref getDocumentWithCompletion:^(FIRDocumentSnapshot * _Nullable snapshot, NSError * _Nullable error) {
if (error) {
[RNFirebaseFirestore promiseRejectException:reject error:error];
} else {
NSDictionary *data = [RNFirebaseFirestoreDocumentReference snapshotToDictionary:snapshot];
resolve(data);
}
}];
}
- (void)set:(NSDictionary *) data
options:(NSDictionary *) options
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
if (options && options[@"merge"]) {
[_ref setData:data options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}];
} else {
[_ref setData:data completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}];
}
}
- (void)update:(NSDictionary *) data
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
[_ref updateData:data completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}];
}
+ (void)handleWriteResponse:(NSError *) error
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
if (error) {
[RNFirebaseFirestore promiseRejectException:reject error:error];
} else {
// Missing fields from web SDK
// writeTime
resolve(@{});
}
}
+ (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot {
NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init];
[snapshot setValue:documentSnapshot.reference.path forKey:@"path"];
[snapshot setValue:documentSnapshot.data forKey:@"data"];
// Missing fields from web SDK
// createTime
// readTime
// updateTime
return snapshot;
}
#endif
@end

View File

@ -13,7 +13,6 @@ const DIRECTIONS = {
DESC: 'DESCENDING', DESC: 'DESCENDING',
desc: 'DESCENDING', desc: 'DESCENDING',
}; };
const DOCUMENT_NAME_FIELD = '__name__';
const OPERATORS = { const OPERATORS = {
'=': 'EQUAL', '=': 'EQUAL',

View File

@ -7,34 +7,34 @@
<key>AD_UNIT_ID_FOR_INTERSTITIAL_TEST</key> <key>AD_UNIT_ID_FOR_INTERSTITIAL_TEST</key>
<string>ca-app-pub-3940256099942544/4411468910</string> <string>ca-app-pub-3940256099942544/4411468910</string>
<key>CLIENT_ID</key> <key>CLIENT_ID</key>
<string>305229645282-22imndi01abc2p6esgtu1i1m9mqrd0ib.apps.googleusercontent.com</string> <string>17067372085-h95lq6v2fbjdl2i1f6pl26iurah37i8p.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key> <key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.305229645282-22imndi01abc2p6esgtu1i1m9mqrd0ib</string> <string>com.googleusercontent.apps.17067372085-h95lq6v2fbjdl2i1f6pl26iurah37i8p</string>
<key>API_KEY</key> <key>API_KEY</key>
<string>AIzaSyAcdVLG5dRzA1ck_fa_xd4Z0cY7cga7S5A</string> <string>AIzaSyC8ZEruBCvS_6woF8_l07ILy1eXaD6J4vQ</string>
<key>GCM_SENDER_ID</key> <key>GCM_SENDER_ID</key>
<string>305229645282</string> <string>17067372085</string>
<key>PLIST_VERSION</key> <key>PLIST_VERSION</key>
<string>1</string> <string>1</string>
<key>BUNDLE_ID</key> <key>BUNDLE_ID</key>
<string>com.invertase.ReactNativeFirebaseDemo</string> <string>com.invertase.ReactNativeFirebaseDemo</string>
<key>PROJECT_ID</key> <key>PROJECT_ID</key>
<string>rnfirebase-b9ad4</string> <string>rnfirebase</string>
<key>STORAGE_BUCKET</key> <key>STORAGE_BUCKET</key>
<string>rnfirebase-b9ad4.appspot.com</string> <string>rnfirebase.appspot.com</string>
<key>IS_ADS_ENABLED</key> <key>IS_ADS_ENABLED</key>
<true/> <true></true>
<key>IS_ANALYTICS_ENABLED</key> <key>IS_ANALYTICS_ENABLED</key>
<false/> <false></false>
<key>IS_APPINVITE_ENABLED</key> <key>IS_APPINVITE_ENABLED</key>
<false/> <false></false>
<key>IS_GCM_ENABLED</key> <key>IS_GCM_ENABLED</key>
<true/> <true></true>
<key>IS_SIGNIN_ENABLED</key> <key>IS_SIGNIN_ENABLED</key>
<true/> <true></true>
<key>GOOGLE_APP_ID</key> <key>GOOGLE_APP_ID</key>
<string>1:305229645282:ios:7b45748cb1117d2d</string> <string>1:17067372085:ios:7b45748cb1117d2d</string>
<key>DATABASE_URL</key> <key>DATABASE_URL</key>
<string>https://rnfirebase-b9ad4.firebaseio.com</string> <string>https://rnfirebase-5579a.firebaseio.com</string>
</dict> </dict>
</plist> </plist>

View File

@ -19,6 +19,7 @@ target 'ReactNativeFirebaseDemo' do
pod 'Firebase/Crash' pod 'Firebase/Crash'
pod 'Firebase/Database' pod 'Firebase/Database'
pod 'Firebase/DynamicLinks' pod 'Firebase/DynamicLinks'
pod 'Firestore', :podspec => 'https://storage.googleapis.com/firebase-preview-drop/ios/firestore/0.7.0/Firestore.podspec.json'
pod 'Firebase/Messaging' pod 'Firebase/Messaging'
pod 'Firebase/RemoteConfig' pod 'Firebase/RemoteConfig'
pod 'Firebase/Storage' pod 'Firebase/Storage'

View File

@ -1,4 +1,10 @@
PODS: PODS:
- BoringSSL (8.2):
- BoringSSL/Implementation (= 8.2)
- BoringSSL/Interface (= 8.2)
- BoringSSL/Implementation (8.2):
- BoringSSL/Interface (= 8.2)
- BoringSSL/Interface (8.2)
- Firebase/AdMob (4.1.0): - Firebase/AdMob (4.1.0):
- Firebase/Core - Firebase/Core
- Google-Mobile-Ads-SDK (= 7.22.0) - Google-Mobile-Ads-SDK (= 7.22.0)
@ -77,6 +83,13 @@ PODS:
- FirebaseAnalytics (~> 4.0) - FirebaseAnalytics (~> 4.0)
- FirebaseCore (~> 4.0) - FirebaseCore (~> 4.0)
- GTMSessionFetcher/Core (~> 1.1) - GTMSessionFetcher/Core (~> 1.1)
- Firestore (0.7.0):
- FirebaseAnalytics (~> 4.0)
- FirebaseAuth (~> 4.1)
- FirebaseCore (~> 4.0)
- gRPC-ProtoRPC (~> 1.0)
- leveldb-library (~> 1.18)
- Protobuf (~> 3.1)
- Google-Mobile-Ads-SDK (7.22.0) - Google-Mobile-Ads-SDK (7.22.0)
- GoogleToolboxForMac/DebugUtils (2.1.1): - GoogleToolboxForMac/DebugUtils (2.1.1):
- GoogleToolboxForMac/Defines (= 2.1.1) - GoogleToolboxForMac/Defines (= 2.1.1)
@ -90,6 +103,22 @@ PODS:
- GoogleToolboxForMac/Defines (= 2.1.1) - GoogleToolboxForMac/Defines (= 2.1.1)
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.1) - GoogleToolboxForMac/NSString+URLArguments (= 2.1.1)
- GoogleToolboxForMac/NSString+URLArguments (2.1.1) - GoogleToolboxForMac/NSString+URLArguments (2.1.1)
- gRPC (1.4.2):
- gRPC-Core (= 1.4.2)
- gRPC-RxLibrary (= 1.4.2)
- gRPC-Core (1.4.2):
- gRPC-Core/Implementation (= 1.4.2)
- gRPC-Core/Interface (= 1.4.2)
- gRPC-Core/Implementation (1.4.2):
- BoringSSL (~> 8.0)
- gRPC-Core/Interface (= 1.4.2)
- nanopb (~> 0.3)
- gRPC-Core/Interface (1.4.2)
- gRPC-ProtoRPC (1.4.2):
- gRPC (= 1.4.2)
- gRPC-RxLibrary (= 1.4.2)
- Protobuf (~> 3.0)
- gRPC-RxLibrary (1.4.2)
- GTMSessionFetcher/Core (1.1.11) - GTMSessionFetcher/Core (1.1.11)
- leveldb-library (1.18.3) - leveldb-library (1.18.3)
- nanopb (0.3.8): - nanopb (0.3.8):
@ -121,11 +150,14 @@ DEPENDENCIES:
- Firebase/Performance - Firebase/Performance
- Firebase/RemoteConfig - Firebase/RemoteConfig
- Firebase/Storage - Firebase/Storage
- Firestore (from `https://storage.googleapis.com/firebase-preview-drop/ios/firestore/0.7.0/Firestore.podspec.json`)
- React (from `../node_modules/react-native`) - React (from `../node_modules/react-native`)
- RNFirebase (from `./../../`) - RNFirebase (from `./../../`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
EXTERNAL SOURCES: EXTERNAL SOURCES:
Firestore:
:podspec: https://storage.googleapis.com/firebase-preview-drop/ios/firestore/0.7.0/Firestore.podspec.json
React: React:
:path: "../node_modules/react-native" :path: "../node_modules/react-native"
RNFirebase: RNFirebase:
@ -134,6 +166,7 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga" :path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS: SPEC CHECKSUMS:
BoringSSL: 4135ae556ee2b82ee85477c39ba917a3dd5424ba
Firebase: ebebf41db7f10e0c7668b6eaaa857fbe599aa478 Firebase: ebebf41db7f10e0c7668b6eaaa857fbe599aa478
FirebaseAnalytics: 76f754d37ca5b04f36856729b6af3ca0152d1069 FirebaseAnalytics: 76f754d37ca5b04f36856729b6af3ca0152d1069
FirebaseAuth: 8d1d2389cf82f891048d6d50d27d044f55ae09a6 FirebaseAuth: 8d1d2389cf82f891048d6d50d27d044f55ae09a6
@ -146,8 +179,13 @@ SPEC CHECKSUMS:
FirebasePerformance: 36bdb0500213b459ae991766801d5dc5399ff231 FirebasePerformance: 36bdb0500213b459ae991766801d5dc5399ff231
FirebaseRemoteConfig: 5b3e3301ef2f237b1b588e8ef3211b5a22e9e15d FirebaseRemoteConfig: 5b3e3301ef2f237b1b588e8ef3211b5a22e9e15d
FirebaseStorage: 661fc1f8d4131891d256b62e82a45ace8b3f0c3b FirebaseStorage: 661fc1f8d4131891d256b62e82a45ace8b3f0c3b
Firestore: 80f352a0b5260500b11d7e4626b81a19d4eba312
Google-Mobile-Ads-SDK: 1bdf1a4244d0553b1840239874c209c01aef055f Google-Mobile-Ads-SDK: 1bdf1a4244d0553b1840239874c209c01aef055f
GoogleToolboxForMac: 8e329f1b599f2512c6b10676d45736bcc2cbbeb0 GoogleToolboxForMac: 8e329f1b599f2512c6b10676d45736bcc2cbbeb0
gRPC: 74b57d3c8a9366e09493828e0a1d27f6d69a79fd
gRPC-Core: 642d29e59e5490374622b0629c2dd1c4c111775c
gRPC-ProtoRPC: 675ef3d484c06967ed2a5f5ee0e510a3756f755e
gRPC-RxLibrary: 7a25c5c25282669a82d1783d7e8a036f53e8ef27
GTMSessionFetcher: 5ad62e8200fa00ed011fe5e08d27fef72c5b1429 GTMSessionFetcher: 5ad62e8200fa00ed011fe5e08d27fef72c5b1429
leveldb-library: 10fb39c39e243db4af1828441162405bbcec1404 leveldb-library: 10fb39c39e243db4af1828441162405bbcec1404
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
@ -156,6 +194,6 @@ SPEC CHECKSUMS:
RNFirebase: 60be8c01b94551a12e7be5431189e8ee8cefcdd3 RNFirebase: 60be8c01b94551a12e7be5431189e8ee8cefcdd3
Yoga: c90474ca3ec1edba44c97b6c381f03e222a9e287 Yoga: c90474ca3ec1edba44c97b6c381f03e222a9e287
PODFILE CHECKSUM: 46b6a553f3c9fd264b449806b373d33b4af518b5 PODFILE CHECKSUM: 49e66d8a1599e426396a3ba88a24baacc7f5423c
COCOAPODS: 1.2.1 COCOAPODS: 1.2.1

106
tests/src/main.firestore.js Normal file
View File

@ -0,0 +1,106 @@
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import fb from './firebase';
global.Promise = require('bluebird');
const firebase = fb.native;
function bootstrap() {
// Remove logging on production
if (!__DEV__) {
console.log = () => {
};
console.warn = () => {
};
console.error = () => {
};
console.disableYellowBox = true;
}
class Root extends Component {
async componentDidMount() {
console.log(`Starting`);
const db = firebase.firestore();
const docRef = await db.collection('chris').add({ first: 'Ada', last: 'Lovelace', born: 1815 });
console.log(`Document written with ID: ${docRef.id}`);
const docRef2 = await db.collection('chris').add({ first: 'Alan', middle: 'Mathison', last: 'Turing', born: 1912 });
console.log(`Document written with ID: ${docRef2.id}`);
await db.collection('chris').doc('manual').set({ first: 'Manual', last: 'Man', born: 1234 });
console.log('Manual document set');
await db.collection('chris').doc().set({ first: 'Auto', last: 'Man', born: 2000 });
console.log('Auto document set');
const docRefT = db.doc(docRef.path);
const docRefS = await docRefT.get();
console.log(`Should be the same as first written ID: ${docRefT.id}`, docRefS.data());
await docRefT.set({ empty: true });
const docRefS2 = await docRefT.get();
console.log(`Should have empty only: ${docRefT.id}`, docRefS2.data());
await docRefT.set({ first: 'Ada', last: 'Lovelace', born: 1815 }, { merge: true });
const docRefS3 = await docRefT.get();
console.log(`Should have everything plus empty: ${docRefT.id}`, docRefS3.data());
await docRefT.update({ first: 'AdaUpdated' });
const docRefS4 = await docRefT.get();
console.log(`Should have updated firstname: ${docRefT.id}`, docRefS4.data());
const docs = await db.collection('chris').get();
const tasks = [];
docs.forEach((doc) => {
console.log(`Cleaning up ${doc.id}`, doc.data());
tasks.push(doc.ref.delete());
});
Promise.all(tasks);
console.log('Finished cleaning collection');
const nycRef = db.collection('chris').doc('NYC');
const sfRef = db.collection('chris').doc('SF');
await db.batch()
.set(nycRef, { name: 'New York City' })
.set(sfRef, { name: 'San Francisco' })
.commit();
const docs2 = await db.collection('chris').get();
docs2.forEach((doc) => {
console.log(`Got ${doc.id}`, doc.data());
});
await db.batch()
.update(nycRef, { population: 1000000 })
.update(sfRef, { name: 'San Fran' })
.commit();
const docs3 = await db.collection('chris').get();
docs3.forEach((doc) => {
console.log(`Got ${doc.id}`, doc.data());
});
await db.batch()
.delete(nycRef)
.delete(sfRef)
.commit();
const docs4 = await db.collection('chris').get();
docs4.forEach((doc) => {
console.log(`Got ${doc.id}`, doc.data());
});
console.log('Finished');
}
render() {
return (
<View>
<Text>Check console logs</Text>
</View>
);
}
}
return Root;
}
export default bootstrap();