[firestore][ios] Type map changes for iOS

This commit is contained in:
Chris Bianca 2017-10-10 17:22:12 +01:00
parent b8751262b7
commit 7c95ceca5b
5 changed files with 136 additions and 6 deletions

View File

@ -274,7 +274,7 @@ public class FirestoreSerialize {
return null; return null;
} }
} else { } else {
Log.e(TAG, "parseTypeMap", new RuntimeException("Cannot convert object of type " + type)); Log.e(TAG, "parseTypeMap: Cannot convert object of type " + type);
return null; return null;
} }
} }

View File

@ -58,7 +58,7 @@ RCT_EXPORT_METHOD(documentBatch:(NSString *) appName
for (NSDictionary *write in writes) { for (NSDictionary *write in writes) {
NSString *type = write[@"type"]; NSString *type = write[@"type"];
NSString *path = write[@"path"]; NSString *path = write[@"path"];
NSDictionary *data = write[@"data"]; NSDictionary *data = [RNFirebaseFirestoreDocumentReference parseJSMap:firestore jsMap:write[@"data"]];
FIRDocumentReference *ref = [firestore documentWithPath:path]; FIRDocumentReference *ref = [firestore documentWithPath:path];

View File

@ -27,6 +27,7 @@
- (void)update:(NSDictionary *)data resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; - (void)update:(NSDictionary *)data resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (BOOL)hasListeners; - (BOOL)hasListeners;
+ (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot; + (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot;
+(NSDictionary *)parseJSMap:(FIRFirestore *) firestore jsMap:(NSDictionary *) jsMap;
@end @end
#else #else

View File

@ -89,12 +89,13 @@ static NSMutableDictionary *_listeners;
options:(NSDictionary *) options options:(NSDictionary *) options
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject { rejecter:(RCTPromiseRejectBlock) reject {
NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_app] jsMap:data];
if (options && options[@"merge"]) { if (options && options[@"merge"]) {
[_ref setData:data options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) { [_ref setData:dictionary options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}]; }];
} else { } else {
[_ref setData:data completion:^(NSError * _Nullable error) { [_ref setData:dictionary completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}]; }];
} }
@ -103,7 +104,8 @@ static NSMutableDictionary *_listeners;
- (void)update:(NSDictionary *) data - (void)update:(NSDictionary *) data
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject { rejecter:(RCTPromiseRejectBlock) reject {
[_ref updateData:data completion:^(NSError * _Nullable error) { NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_app] jsMap:data];
[_ref updateData:dictionary completion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
}]; }];
} }
@ -126,7 +128,7 @@ static NSMutableDictionary *_listeners;
NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init]; NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init];
[snapshot setValue:documentSnapshot.reference.path forKey:@"path"]; [snapshot setValue:documentSnapshot.reference.path forKey:@"path"];
if (documentSnapshot.exists) { if (documentSnapshot.exists) {
[snapshot setValue:documentSnapshot.data forKey:@"data"]; [snapshot setValue:[RNFirebaseFirestoreDocumentReference buildNativeMap:documentSnapshot.data] forKey:@"data"];
} }
if (documentSnapshot.metadata) { if (documentSnapshot.metadata) {
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init]; NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
@ -159,6 +161,121 @@ static NSMutableDictionary *_listeners;
[_emitter sendEventWithName:FIRESTORE_DOCUMENT_SYNC_EVENT body:event]; [_emitter sendEventWithName:FIRESTORE_DOCUMENT_SYNC_EVENT body:event];
} }
+ (NSDictionary *)buildNativeMap:(NSDictionary *)nativeMap {
NSMutableDictionary *map = [[NSMutableDictionary alloc] init];
[nativeMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSDictionary *typeMap = [RNFirebaseFirestoreDocumentReference buildTypeMap:obj];
map[key] = typeMap;
}];
return map;
}
+ (NSArray *)buildNativeArray:(NSArray *)nativeArray {
NSMutableArray *array = [[NSMutableArray alloc] init];
[nativeArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSDictionary *typeMap = [RNFirebaseFirestoreDocumentReference buildTypeMap:obj];
[array addObject:typeMap];
}];
return array;
}
+ (NSDictionary *)buildTypeMap:(id) value {
NSMutableDictionary *typeMap = [[NSMutableDictionary alloc] init];
if (!value) {
typeMap[@"type"] = @"null";
} else if ([value isKindOfClass:[NSString class]]) {
typeMap[@"type"] = @"string";
typeMap[@"value"] = value;
} else if ([value isKindOfClass:[NSDictionary class]]) {
typeMap[@"type"] = @"object";
typeMap[@"value"] = [RNFirebaseFirestoreDocumentReference buildNativeMap:value];
} else if ([value isKindOfClass:[NSArray class]]) {
typeMap[@"type"] = @"array";
typeMap[@"value"] = [RNFirebaseFirestoreDocumentReference buildNativeArray:value];
} else if ([value isKindOfClass:[FIRDocumentReference class]]) {
typeMap[@"type"] = @"reference";
FIRDocumentReference *ref = (FIRDocumentReference *)value;
typeMap[@"value"] = [ref path];
} else if ([value isKindOfClass:[FIRGeoPoint class]]) {
typeMap[@"type"] = @"geopoint";
FIRGeoPoint *point = (FIRGeoPoint *)value;
NSMutableDictionary *geopoint = [[NSMutableDictionary alloc] init];
geopoint[@"latitude"] = @([point latitude]);
geopoint[@"longitude"] = @([point longitude]);
typeMap[@"value"] = geopoint;
} else if ([value isKindOfClass:[NSDate class]]) {
typeMap[@"type"] = @"date";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
typeMap[@"value"] = [dateFormatter stringFromDate:(NSDate *)value];
} else if ([value isKindOfClass:[NSNumber class]]) {
NSNumber *number = (NSNumber *)value;
if (number == (void*)kCFBooleanFalse || number == (void*)kCFBooleanTrue) {
typeMap[@"type"] = @"boolean";
} else {
typeMap[@"type"] = @"number";
}
typeMap[@"value"] = value;
} else {
// TODO: Log an error
typeMap[@"type"] = @"null";
}
return typeMap;
}
+(NSDictionary *)parseJSMap:(FIRFirestore *) firestore
jsMap:(NSDictionary *) jsMap {
NSMutableDictionary* map = [[NSMutableDictionary alloc] init];
if (jsMap) {
[jsMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
map[key] = [RNFirebaseFirestoreDocumentReference parseJSTypeMap:firestore jsTypeMap:obj];
}];
}
return map;
}
+(NSArray *)parseJSArray:(FIRFirestore *) firestore
jsArray:(NSArray *) jsArray {
NSMutableArray* array = [[NSMutableArray alloc] init];
if (jsArray) {
[jsArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[array addObject:[RNFirebaseFirestoreDocumentReference parseJSTypeMap:firestore jsTypeMap:obj]];
}];
}
return array;
}
+(id)parseJSTypeMap:(FIRFirestore *) firestore
jsTypeMap:(NSDictionary *) jsTypeMap {
NSString *type = jsTypeMap[@"type"];
id value = jsTypeMap[@"value"];
if ([type isEqualToString:@"array"]) {
return [RNFirebaseFirestoreDocumentReference parseJSArray:firestore jsArray:value];
} else if ([type isEqualToString:@"object"]) {
return [RNFirebaseFirestoreDocumentReference parseJSMap:firestore jsMap:value];
} else if ([type isEqualToString:@"reference"]) {
return [firestore documentWithPath:value];
} else if ([type isEqualToString:@"geopoint"]) {
NSDictionary* geopoint = (NSDictionary*)value;
NSNumber *latitude = geopoint[@"latitude"];
NSNumber *longitude = geopoint[@"longitude"];
return [[FIRGeoPoint alloc] initWithLatitude:[latitude doubleValue] longitude:[longitude doubleValue]];
} else if ([type isEqualToString:@"date"]) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
return [dateFormatter dateFromString:value];
} else if ([type isEqualToString:@"boolean"] || [type isEqualToString:@"number"] || [type isEqualToString:@"string"] || [type isEqualToString:@"null"]) {
return value;
} else {
// TODO: Log error
return nil;
}
}
#endif #endif
@end @end

View File

@ -412,6 +412,18 @@ function documentReferenceTests({ describe, it, context, firebase }) {
}); });
}); });
context('types', () => {
it('should handle Boolean field', async () => {
const docRef = firebase.native.firestore().doc('document-tests/reference');
await docRef.set({
field: true,
});
const doc = await docRef.get();
should.equal(doc.data().field, true);
});
});
context('types', () => { context('types', () => {
it('should handle Date field', async () => { it('should handle Date field', async () => {
const docRef = firebase.native.firestore().doc('document-tests/reference'); const docRef = firebase.native.firestore().doc('document-tests/reference');