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
JavaScript
/**
*
* 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);
}
}