diff --git a/android/src/main/java/io/fullstack/firestack/database/FirestackDatabaseReference.java b/android/src/main/java/io/fullstack/firestack/database/FirestackDatabaseReference.java index 223cf0a..47e6f11 100644 --- a/android/src/main/java/io/fullstack/firestack/database/FirestackDatabaseReference.java +++ b/android/src/main/java/io/fullstack/firestack/database/FirestackDatabaseReference.java @@ -68,7 +68,7 @@ public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) { @Override public void onCancelled(DatabaseError error) { - handleDatabaseError(eventName, error); + handleDatabaseError(error); } }; mQuery.addChildEventListener(mEventListener); @@ -90,7 +90,7 @@ public void onDataChange(DataSnapshot dataSnapshot) { @Override public void onCancelled(DatabaseError error) { - handleDatabaseError("value", error); + handleDatabaseError(error); } }; mQuery.addValueEventListener(mValueListener); @@ -162,22 +162,22 @@ private void handleDatabaseEvent(final String name, final DataSnapshot dataSnaps WritableMap data = Utils.dataSnapshotToMap(name, mPath, mModifiersString, dataSnapshot); WritableMap evt = Arguments.createMap(); evt.putString("eventName", name); - evt.putString("path", mPath); - evt.putString("modifiersString", mModifiersString); evt.putMap("body", data); Utils.sendEvent(mReactContext, "database_event", evt); } - private void handleDatabaseError(final String name, final DatabaseError error) { + private void handleDatabaseError(final DatabaseError error) { WritableMap err = Arguments.createMap(); + err.putString("eventName", "database_error"); + err.putString("path", mPath); + err.putString("modifiersString", mModifiersString); err.putInt("errorCode", error.getCode()); err.putString("errorDetails", error.getDetails()); - err.putString("description", error.getMessage()); + err.putString("msg", error.getMessage()); WritableMap evt = Arguments.createMap(); - evt.putString("eventName", name); - evt.putString("path", mPath); + evt.putString("eventName", "database_error"); evt.putMap("body", err); Utils.sendEvent(mReactContext, "database_error", evt); diff --git a/ios/Firestack/FirestackDatabase.m b/ios/Firestack/FirestackDatabase.m index bdb10fa..eb11d89 100644 --- a/ios/Firestack/FirestackDatabase.m +++ b/ios/Firestack/FirestackDatabase.m @@ -58,7 +58,9 @@ - (void) addEventHandler:(NSString *) eventName }; id errorBlock = ^(NSError * _Nonnull error) { NSLog(@"Error onDBEvent: %@", [error debugDescription]); - [self getAndSendDatabaseError:error withPath: _path]; + [self getAndSendDatabaseError:error + path:_path + modifiersString:_modifiersString]; }; int eventType = [self eventTypeFromName:eventName]; FIRDatabaseHandle handle = [_query observeEventType:eventType @@ -158,11 +160,13 @@ - (NSDictionary *) snapshotToDict:(FIRDataSnapshot *) snapshot } - (NSDictionary *) getAndSendDatabaseError:(NSError *) error - withPath:(NSString *) path + path:(NSString *) path + modifiersString:(NSString *) modifiersString { NSDictionary *evt = @{ @"eventName": DATABASE_ERROR_EVENT, @"path": path, + @"modifiersString": modifiersString, @"msg": [error debugDescription] }; [self sendJSEvent:DATABASE_ERROR_EVENT title:DATABASE_ERROR_EVENT props: evt]; diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index f745391..0d72aa3 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -19,6 +19,7 @@ export default class Database extends Base { constructor(firestack: Object, options: Object = {}) { super(firestack, options); this.subscriptions = {}; + this.errorSubscriptions = {}; this.serverTimeOffset = 0; this.persistenceEnabled = false; this.namespace = 'firestack:database'; @@ -86,13 +87,17 @@ export default class Database extends Base { * @param cb * @returns {*} */ - on(path: string, modifiersString: string, modifiers: Array, eventName: string, cb: () => void) { + on(path: string, modifiersString: string, modifiers: Array, eventName: string, cb: () => void, errorCb: () => void) { const handle = this._handle(path, modifiersString); this.log.debug('adding on listener', handle); if (!this.subscriptions[handle]) this.subscriptions[handle] = {}; if (!this.subscriptions[handle][eventName]) this.subscriptions[handle][eventName] = []; this.subscriptions[handle][eventName].push(cb); + if (errorCb) { + if (!this.errorSubscriptions[handle]) this.errorSubscriptions[handle] = []; + this.errorSubscriptions[handle].push(errorCb); + } return promisify('on', FirestackDatabase)(path, modifiersString, modifiers, eventName); } @@ -129,7 +134,7 @@ export default class Database extends Base { } else { this.subscriptions[handle] = {}; } - + this.errorSubscriptions[handle] = []; return promisify('off', FirestackDatabase)(path, modifiersString, eventName); } @@ -207,6 +212,12 @@ export default class Database extends Base { * @private */ _handleDatabaseError(err: Object) { - this.log.debug('_handleDatabaseError ->', err); + const body = err.body || {}; + const { path, modifiersString, eventName, msg } = body; + const handle = this._handle(path, modifiersString); + + this.log.debug('_handleDatabaseError ->', handle, eventName, err); + + if (this.errorSubscriptions[handle]) this.errorSubscriptions[handle].forEach((cb) => cb(new Error(msg))); } } diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index e2ded4b..6eef4f1 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -94,13 +94,14 @@ export default class Reference extends ReferenceBase { }); } - on(eventName: string, cb: () => any) { + on(eventName: string, cb: () => any, errorCb: () => any) { if (!isFunction(cb)) throw new Error('The specified callback must be a function'); + if (errorCb && !isFunction(errorCb)) throw new Error('The specified error callback must be a function'); const path = this._dbPath(); const modifiers = this.query.getModifiers(); const modifiersString = this.query.getModifiersString(); this.log.debug('adding reference.on', path, modifiersString, eventName); - return this.db.on(path, modifiersString, modifiers, eventName, cb); + return this.db.on(path, modifiersString, modifiers, eventName, cb, errorCb); } once(eventName: string = 'once', cb: (snapshot: Object) => void) {