UNPKG

react-native-firebase-compiled

Version:

A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Functions, Messaging (FCM), Remote Config, Sto

183 lines (145 loc) 6.88 kB
/** * * DocumentReference representation wrapper */ import CollectionReference from './CollectionReference'; import DocumentSnapshot from './DocumentSnapshot'; import { parseUpdateArgs } from './utils'; import { buildNativeMap } from './utils/serialize'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { getLogger } from '../../utils/log'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; import { getNativeModule } from '../../utils/native'; /** * @class DocumentReference */ export default class DocumentReference { constructor(firestore, documentPath) { this._documentPath = documentPath; this._firestore = firestore; } get firestore() { return this._firestore; } get id() { return this._documentPath.id; } get parent() { const parentPath = this._documentPath.parent(); // $FlowExpectedError: parentPath can never be null return new CollectionReference(this._firestore, parentPath); } get path() { return this._documentPath.relativeName; } collection(collectionPath) { const path = this._documentPath.child(collectionPath); if (!path.isCollection) { throw new Error('Argument "collectionPath" must point to a collection.'); } return new CollectionReference(this._firestore, path); } delete() { return getNativeModule(this._firestore).documentDelete(this.path); } get(options) { if (options) { if (!isObject(options)) { return Promise.reject(new Error('DocumentReference.get failed: First argument must be an object.')); } if (options.source && options.source !== 'default' && options.source !== 'server' && options.source !== 'cache') { return Promise.reject(new Error('DocumentReference.get failed: GetOptions.source must be one of `default`, `server` or `cache`.')); } } return getNativeModule(this._firestore).documentGet(this.path, options).then(result => new DocumentSnapshot(this._firestore, result)); } onSnapshot(optionsOrObserverOrOnNext, observerOrOnNextOrOnError, onError) { let observer; let docListenOptions = {}; // Called with: onNext, ?onError if (isFunction(optionsOrObserverOrOnNext)) { if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) { throw new Error('DocumentReference.onSnapshot failed: Second argument must be a valid function.'); } // $FlowExpectedError: Not coping with the overloaded method signature observer = { next: optionsOrObserverOrOnNext, error: observerOrOnNextOrOnError }; } else if (optionsOrObserverOrOnNext && isObject(optionsOrObserverOrOnNext)) { // Called with: Observer if (optionsOrObserverOrOnNext.next) { if (isFunction(optionsOrObserverOrOnNext.next)) { if (optionsOrObserverOrOnNext.error && !isFunction(optionsOrObserverOrOnNext.error)) { throw new Error('DocumentReference.onSnapshot failed: Observer.error must be a valid function.'); } // $FlowExpectedError: Not coping with the overloaded method signature observer = { next: optionsOrObserverOrOnNext.next, error: optionsOrObserverOrOnNext.error }; } else { throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.'); } } else if (Object.prototype.hasOwnProperty.call(optionsOrObserverOrOnNext, 'includeMetadataChanges')) { docListenOptions = optionsOrObserverOrOnNext; // Called with: Options, onNext, ?onError if (isFunction(observerOrOnNextOrOnError)) { if (onError && !isFunction(onError)) { throw new Error('DocumentReference.onSnapshot failed: Third argument must be a valid function.'); } // $FlowExpectedError: Not coping with the overloaded method signature observer = { next: observerOrOnNextOrOnError, error: onError }; // Called with Options, Observer } else if (observerOrOnNextOrOnError && isObject(observerOrOnNextOrOnError) && observerOrOnNextOrOnError.next) { if (isFunction(observerOrOnNextOrOnError.next)) { if (observerOrOnNextOrOnError.error && !isFunction(observerOrOnNextOrOnError.error)) { throw new Error('DocumentReference.onSnapshot failed: Observer.error must be a valid function.'); } observer = { next: observerOrOnNextOrOnError.next, error: observerOrOnNextOrOnError.error }; } else { throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.'); } } else { throw new Error('DocumentReference.onSnapshot failed: Second argument must be a function or observer.'); } } else { throw new Error('DocumentReference.onSnapshot failed: First argument must be a function, observer or options.'); } } else { throw new Error('DocumentReference.onSnapshot failed: Called with invalid arguments.'); } const listenerId = firestoreAutoId(); const listener = nativeDocumentSnapshot => { const documentSnapshot = new DocumentSnapshot(this.firestore, nativeDocumentSnapshot); observer.next(documentSnapshot); }; // Listen to snapshot events SharedEventEmitter.addListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener); // Listen for snapshot error events if (observer.error) { SharedEventEmitter.addListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), observer.error); } // Add the native listener getNativeModule(this._firestore).documentOnSnapshot(this.path, listenerId, docListenOptions); // Return an unsubscribe method return this._offDocumentSnapshot.bind(this, listenerId, listener); } set(data, options) { const nativeData = buildNativeMap(data); return getNativeModule(this._firestore).documentSet(this.path, nativeData, options); } update(...args) { const data = parseUpdateArgs(args, 'DocumentReference.update'); const nativeData = buildNativeMap(data); return getNativeModule(this._firestore).documentUpdate(this.path, nativeData); } /** * INTERNALS */ /** * Remove document snapshot listener * @param listener */ _offDocumentSnapshot(listenerId, listener) { getLogger(this._firestore).info('Removing onDocumentSnapshot listener'); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), listener); getNativeModule(this._firestore).documentOffSnapshot(this.path, listenerId); } }