Skip to content

Commit

Permalink
[firestore] Add metadata and bring methods in sync with web SDK refer…
Browse files Browse the repository at this point in the history
…ence
  • Loading branch information
chrisbianca committed Oct 5, 2017
1 parent 870cb4e commit f350c2b
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 241 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class FirestoreSerialize {
private static final String KEY_DOC_CHANGE_OLD_INDEX = "oldIndex";
private static final String KEY_DOC_CHANGE_TYPE = "type";
private static final String KEY_DOCUMENTS = "documents";
private static final String KEY_METADATA = "metadata";
private static final String KEY_PATH = "path";

/**
Expand All @@ -35,10 +36,13 @@ static WritableMap snapshotToWritableMap(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
documentMap.putMap(KEY_DATA, objectMapToWritable(documentSnapshot.getData()));
}
// Missing fields from web SDK
// createTime
// readTime
// updateTime
// metadata
if (documentSnapshot.getMetadata() != null) {
WritableMap metadata = Arguments.createMap();
metadata.putBoolean("fromCache", documentSnapshot.getMetadata().isFromCache());
metadata.putBoolean("hasPendingWrites", documentSnapshot.getMetadata().hasPendingWrites());
documentMap.putMap(KEY_METADATA, metadata);
}

return documentMap;
}
Expand All @@ -57,6 +61,14 @@ public static WritableMap snapshotToWritableMap(QuerySnapshot querySnapshot) {
}
queryMap.putArray(KEY_DOCUMENTS, documents);

// metadata
if (querySnapshot.getMetadata() != null) {
WritableMap metadata = Arguments.createMap();
metadata.putBoolean("fromCache", querySnapshot.getMetadata().isFromCache());
metadata.putBoolean("hasPendingWrites", querySnapshot.getMetadata().hasPendingWrites());
queryMap.putMap(KEY_METADATA, metadata);
}

return queryMap;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void collectionOnSnapshot(String appName, String path, ReadableArray filt

@ReactMethod
public void documentBatch(final String appName, final ReadableArray writes,
final ReadableMap commitOptions, final Promise promise) {
final Promise promise) {
FirebaseFirestore firestore = getFirestoreForApp(appName);
WriteBatch batch = firestore.batch();
final List<Object> writesArray = Utils.recursivelyDeconstructReadableArray(writes);
Expand Down Expand Up @@ -100,16 +100,10 @@ public void documentBatch(final String appName, final ReadableArray writes,
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "set:onComplete:success");
WritableArray result = Arguments.createArray();
for (Object w : writesArray) {
// Missing fields from web SDK
// writeTime
result.pushMap(Arguments.createMap());
}
promise.resolve(result);
Log.d(TAG, "documentBatch:onComplete:success");
promise.resolve(null);
} else {
Log.e(TAG, "set:onComplete:failure", task.getException());
Log.e(TAG, "documentBatch:onComplete:failure", task.getException());
RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException());
}
}
Expand All @@ -129,9 +123,9 @@ public void documentCreate(String appName, String path, ReadableMap data, final
}

@ReactMethod
public void documentDelete(String appName, String path, ReadableMap options, final Promise promise) {
public void documentDelete(String appName, String path, final Promise promise) {
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
ref.delete(options, promise);
ref.delete(promise);
}

@ReactMethod
Expand Down Expand Up @@ -249,63 +243,67 @@ static WritableMap getJSError(FirebaseFirestoreException nativeException) {
break;
case CANCELLED:
code = ErrorUtils.getCodeWithService(service, "cancelled");
message = ErrorUtils.getMessageWithService("Cancelled.", service, code);
message = ErrorUtils.getMessageWithService("The operation was cancelled (typically by the caller).", service, code);
break;
case UNKNOWN:
code = ErrorUtils.getCodeWithService(service, "unknown");
message = ErrorUtils.getMessageWithService("An unknown error occurred.", service, code);
message = ErrorUtils.getMessageWithService("Unknown error or an error from a different error domain.", service, code);
break;
case INVALID_ARGUMENT:
code = ErrorUtils.getCodeWithService(service, "invalid-argument");
message = ErrorUtils.getMessageWithService("Invalid argument.", service, code);
message = ErrorUtils.getMessageWithService("Client specified an invalid argument.", service, code);
break;
case DEADLINE_EXCEEDED:
code = ErrorUtils.getCodeWithService(service, "deadline-exceeded");
message = ErrorUtils.getMessageWithService("Deadline expired before operation could complete.", service, code);
break;
case NOT_FOUND:
code = ErrorUtils.getCodeWithService(service, "not-found");
message = ErrorUtils.getMessageWithService("Not found.", service, code);
message = ErrorUtils.getMessageWithService("Some requested document was not found.", service, code);
break;
case ALREADY_EXISTS:
code = ErrorUtils.getCodeWithService(service, "already-exists");
message = ErrorUtils.getMessageWithService("Already exists.", service, code);
message = ErrorUtils.getMessageWithService("Some document that we attempted to create already exists.", service, code);
break;
case PERMISSION_DENIED:
code = ErrorUtils.getCodeWithService(service, "permission-denied");
message = ErrorUtils.getMessageWithService("Permission denied.", service, code);
message = ErrorUtils.getMessageWithService("The caller does not have permission to execute the specified operation.", service, code);
break;
case RESOURCE_EXHAUSTED:
code = ErrorUtils.getCodeWithService(service, "resource-exhausted");
message = ErrorUtils.getMessageWithService("Resource exhausted.", service, code);
message = ErrorUtils.getMessageWithService("Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space.", service, code);
break;
case FAILED_PRECONDITION:
code = ErrorUtils.getCodeWithService(service, "failed-precondition");
message = ErrorUtils.getMessageWithService("Failed precondition.", service, code);
message = ErrorUtils.getMessageWithService("Operation was rejected because the system is not in a state required for the operation`s execution.", service, code);
break;
case ABORTED:
code = ErrorUtils.getCodeWithService(service, "aborted");
message = ErrorUtils.getMessageWithService("Aborted.", service, code);
message = ErrorUtils.getMessageWithService("The operation was aborted, typically due to a concurrency issue like transaction aborts, etc.", service, code);
break;
case OUT_OF_RANGE:
code = ErrorUtils.getCodeWithService(service, "out-of-range");
message = ErrorUtils.getMessageWithService("Out of range.", service, code);
message = ErrorUtils.getMessageWithService("Operation was attempted past the valid range.", service, code);
break;
case UNIMPLEMENTED:
code = ErrorUtils.getCodeWithService(service, "unimplemented");
message = ErrorUtils.getMessageWithService("Unimplemented.", service, code);
message = ErrorUtils.getMessageWithService("Operation is not implemented or not supported/enabled.", service, code);
break;
case INTERNAL:
code = ErrorUtils.getCodeWithService(service, "internal");
message = ErrorUtils.getMessageWithService("Internal.", service, code);
message = ErrorUtils.getMessageWithService("Internal errors.", service, code);
break;
case UNAVAILABLE:
code = ErrorUtils.getCodeWithService(service, "unavailable");
message = ErrorUtils.getMessageWithService("Unavailable.", service, code);
message = ErrorUtils.getMessageWithService("The service is currently unavailable.", service, code);
break;
case DATA_LOSS:
code = ErrorUtils.getCodeWithService(service, "data-loss");
message = ErrorUtils.getMessageWithService("Data loss.", service, code);
message = ErrorUtils.getMessageWithService("Unrecoverable data loss or corruption.", service, code);
break;
case UNAUTHENTICATED:
code = ErrorUtils.getCodeWithService(service, "unauthenticated");
message = ErrorUtils.getMessageWithService("Unauthenticated.", service, code);
message = ErrorUtils.getMessageWithService("The request does not have valid authentication credentials for the operation.", service, code);
break;
default:
code = ErrorUtils.getCodeWithService(service, "unknown");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,13 @@ public void create(ReadableMap data, Promise promise) {
// Not supported on Android out of the box
}

public void delete(final ReadableMap options, final Promise promise) {
public void delete(final Promise promise) {
this.ref.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "delete:onComplete:success");
// Missing fields from web SDK
// writeTime
promise.resolve(Arguments.createMap());
promise.resolve(null);
} else {
Log.e(TAG, "delete:onComplete:failure", task.getException());
RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException());
Expand Down Expand Up @@ -122,9 +120,7 @@ public void set(final ReadableMap data, final ReadableMap options, final Promise
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "set:onComplete:success");
// Missing fields from web SDK
// writeTime
promise.resolve(Arguments.createMap());
promise.resolve(null);
} else {
Log.e(TAG, "set:onComplete:failure", task.getException());
RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException());
Expand All @@ -140,9 +136,7 @@ public void update(final ReadableMap data, final Promise promise) {
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "update:onComplete:success");
// Missing fields from web SDK
// writeTime
promise.resolve(Arguments.createMap());
promise.resolve(null);
} else {
Log.e(TAG, "update:onComplete:failure", task.getException());
RNFirebaseFirestore.promiseRejectException(promise, (FirebaseFirestoreException)task.getException());
Expand Down
12 changes: 2 additions & 10 deletions ios/RNFirebase/firestore/RNFirebaseFirestore.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ - (id)init {

RCT_EXPORT_METHOD(documentBatch:(NSString *) appName
writes:(NSArray *) writes
commitOptions:(NSDictionary *) commitOptions
resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) {
FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appName];
Expand Down Expand Up @@ -80,13 +79,7 @@ - (id)init {
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);
resolve(nil);
}
}];
}
Expand All @@ -108,10 +101,9 @@ - (id)init {

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];
[[self getDocumentForAppPath:appName path:path] delete:resolve rejecter:reject];
}

RCT_EXPORT_METHOD(documentGet:(NSString *) appName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ + (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"];
if (querySnapshot.metadata) {
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setValue:@(querySnapshot.metadata.fromCache) forKey:@"fromCache"];
[metadata setValue:@(querySnapshot.metadata.hasPendingWrites) forKey:@"hasPendingWrites"];
[snapshot setValue:metadata forKey:@"metadata"];
}

return snapshot;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
- (id)initWithPath:(RCTEventEmitter *)emitter app:(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)delete:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
+ (void)offSnapshot:(NSString *)listenerId;
- (void)onSnapshot:(NSString *)listenerId;
Expand Down
18 changes: 8 additions & 10 deletions ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ - (void)create:(NSDictionary *) data
// Not supported on iOS out of the box
}

- (void)delete:(NSDictionary *)options
resolver:(RCTPromiseResolveBlock) resolve
- (void)delete:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject {
[_ref deleteDocumentWithCompletion:^(NSError * _Nullable error) {
[RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject];
Expand Down Expand Up @@ -115,9 +114,7 @@ + (void)handleWriteResponse:(NSError *) error
if (error) {
[RNFirebaseFirestore promiseRejectException:reject error:error];
} else {
// Missing fields from web SDK
// writeTime
resolve(@{});
resolve(nil);
}
}

Expand All @@ -127,11 +124,12 @@ + (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot {
if (documentSnapshot.exists) {
[snapshot setValue:documentSnapshot.data forKey:@"data"];
}
// Missing fields from web SDK
// createTime
// readTime
// updateTime

if (documentSnapshot.metadata) {
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setValue:@(documentSnapshot.metadata.fromCache) forKey:@"fromCache"];
[metadata setValue:@(documentSnapshot.metadata.hasPendingWrites) forKey:@"hasPendingWrites"];
[snapshot setValue:metadata forKey:@"metadata"];
}
return snapshot;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/modules/firestore/CollectionReference.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default class CollectionReference {
return parentPath ? new DocumentReference(this._firestore, parentPath) : null;
}

add(data: { [string]: any }): Promise<DocumentReference> {
add(data: Object): Promise<DocumentReference> {
const documentRef = this.doc();
return documentRef.set(data)
.then(() => Promise.resolve(documentRef));
Expand Down
43 changes: 6 additions & 37 deletions lib/modules/firestore/DocumentReference.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,12 @@
import CollectionReference from './CollectionReference';
import DocumentSnapshot from './DocumentSnapshot';
import Path from './Path';
import INTERNALS from './../../internals';
import { firestoreAutoId } from '../../utils';

export type DeleteOptions = {
lastUpdateTime?: string,
}

export type WriteOptions = {
merge?: boolean,
}

export type WriteResult = {
writeTime: string,
}

/**
* @class DocumentReference
*/
Expand All @@ -40,9 +31,9 @@ export default class DocumentReference {
return this._documentPath.id;
}

get parent(): CollectionReference | null {
get parent(): CollectionReference {
const parentPath = this._documentPath.parent();
return parentPath ? new CollectionReference(this._firestore, parentPath) : null;
return new CollectionReference(this._firestore, parentPath);
}

get path(): string {
Expand All @@ -58,15 +49,9 @@ export default class DocumentReference {
return new CollectionReference(this._firestore, path);
}

create(data: { [string]: any }): Promise<WriteResult> {
/* return this._firestore._native
.documentCreate(this.path, data); */
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('DocumentReference', 'create'));
}

delete(deleteOptions?: DeleteOptions): Promise<WriteResult> {
delete(): Promise<void> {
return this._firestore._native
.documentDelete(this.path, deleteOptions);
.documentDelete(this.path);
}

get(): Promise<DocumentSnapshot> {
Expand All @@ -75,21 +60,6 @@ export default class DocumentReference {
.then(result => new DocumentSnapshot(this._firestore, result));
}

getCollections(): Promise<CollectionReference[]> {
/* return this._firestore._native
.documentCollections(this.path)
.then((collectionIds) => {
const collections = [];
for (const collectionId of collectionIds) {
collections.push(this.collection(collectionId));
}
return collections;
}); */
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('DocumentReference', 'getCollections'));
}

onSnapshot(onNext: Function, onError?: Function): () => void {
// TODO: Validation
const listenerId = firestoreAutoId();
Expand Down Expand Up @@ -121,13 +91,12 @@ export default class DocumentReference {
return this._offDocumentSnapshot.bind(this, listenerId, listener);
}

set(data: { [string]: any }, writeOptions?: WriteOptions): Promise<WriteResult> {
set(data: Object, writeOptions?: WriteOptions): Promise<void> {
return this._firestore._native
.documentSet(this.path, data, writeOptions);
}

// TODO: Update to new update method signature
update(data: { [string]: any }): Promise<WriteResult> {
update(data: Object): Promise<void> {
return this._firestore._native
.documentUpdate(this.path, data);
}
Expand Down
Loading

0 comments on commit f350c2b

Please sign in to comment.