[firestore][android][js] Add document onSnapshot support plus tests

This commit is contained in:
Chris Bianca
2017-10-02 13:11:38 +01:00
parent b4743ffa8b
commit cda1c27b5c
11 changed files with 597 additions and 81 deletions

View File

@@ -19,6 +19,9 @@ export type WriteResult = {
writeTime: string,
}
// track all event registrations
let listeners = 0;
/**
* @class DocumentReference
*/
@@ -89,8 +92,30 @@ export default class DocumentReference {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('DocumentReference', 'getCollections'));
}
onSnapshot(onNext: () => any, onError?: () => any): () => void {
// TODO
onSnapshot(onNext: Function, onError?: Function): () => void {
// TODO: Validation
const listenerId = listeners++;
// Listen to snapshot events
this._firestore.on(
this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`),
onNext,
);
// Listen for snapshot error events
if (onError) {
this._firestore.on(
this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`),
onError,
);
}
// Add the native listener
this._firestore._native
.documentOnSnapshot(this.path, listenerId);
// Return an unsubscribe method
return this._offDocumentSnapshot.bind(this, listenerId, onNext);
}
set(data: { [string]: any }, writeOptions?: WriteOptions): Promise<WriteResult> {
@@ -105,16 +130,11 @@ export default class DocumentReference {
}
/**
* INTERNALS
* Remove auth change listener
* @param listener
*/
/**
* Generate a string that uniquely identifies this DocumentReference
*
* @return {string}
* @private
*/
_getDocumentKey() {
return `$${this._firestore._appName}$/${this.path}`;
_offDocumentSnapshot(listenerId: number, listener: Function) {
this._firestore.log.info('Removing onDocumentSnapshot listener');
this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), listener);
}
}

View File

@@ -200,7 +200,7 @@ export default class Query {
}
stream(): Stream<DocumentSnapshot> {
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('Query', 'stream'));
}
where(fieldPath: string, opStr: Operator, value: any): Query {

View File

@@ -16,6 +16,14 @@ import INTERNALS from './../../internals';
const unquotedIdentifier_ = '(?:[A-Za-z_][A-Za-z_0-9]*)';
const UNQUOTED_IDENTIFIER_REGEX = new RegExp(`^${unquotedIdentifier_}$`);
type DocumentSyncEvent = {
appName: string,
document?: DocumentSnapshot,
error?: Object,
listenerId: number,
path: string,
}
/**
* @class Firestore
*/
@@ -28,6 +36,20 @@ export default class Firestore extends ModuleBase {
constructor(firebaseApp: Object, options: Object = {}) {
super(firebaseApp, options, true);
this._referencePath = new Path([]);
this.addListener(
// sub to internal native event - this fans out to
// public event name: onCollectionSnapshot
this._getAppEventName('firestore_collection_sync_event'),
this._onCollectionSyncEvent.bind(this),
);
this.addListener(
// sub to internal native event - this fans out to
// public event name: onDocumentSnapshot
this._getAppEventName('firestore_document_sync_event'),
this._onDocumentSyncEvent.bind(this),
);
}
batch(): WriteBatch {
@@ -107,6 +129,37 @@ export default class Firestore extends ModuleBase {
return fieldPath;
}
/**
* INTERNALS
*/
/**
* Internal collection sync listener
* @param event
* @private
*/
_onCollectionSyncEvent(event: DocumentSyncEvent) {
if (event.error) {
this.emit(this._getAppEventName(`onCollectionSnapshotError:${event.listenerId}`, event.error));
} else {
this.emit(this._getAppEventName(`onCollectionSnapshot:${event.listenerId}`, event.document));
}
}
/**
* Internal document sync listener
* @param event
* @private
*/
_onDocumentSyncEvent(event: DocumentSyncEvent) {
if (event.error) {
this.emit(this._getAppEventName(`onDocumentSnapshotError:${event.listenerId}`), event.error);
} else {
const snapshot = new DocumentSnapshot(this, event.document);
this.emit(this._getAppEventName(`onDocumentSnapshot:${event.listenerId}`), snapshot);
}
}
}
export const statics = {

View File

@@ -29,6 +29,10 @@ const NATIVE_MODULE_EVENTS = {
'database_transaction_event',
// 'database_server_offset', // TODO
],
Firestore: [
'firestore_collection_sync_event',
'firestore_document_sync_event',
],
};
const DEFAULTS = {