mirror of
https://github.com/zhigang1992/react-native-firebase.git
synced 2026-04-24 04:24:52 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -5,12 +5,21 @@
|
||||
import CollectionReference from './CollectionReference';
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import Path from './Path';
|
||||
import { firestoreAutoId } from '../../utils';
|
||||
import { firestoreAutoId, isFunction, isObject, isString } from '../../utils';
|
||||
|
||||
export type WriteOptions = {
|
||||
merge?: boolean,
|
||||
}
|
||||
|
||||
type DocumentListenOptions = {
|
||||
includeMetadataChanges: boolean,
|
||||
}
|
||||
|
||||
type Observer = {
|
||||
next: (DocumentSnapshot) => void,
|
||||
error?: (Object) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* @class DocumentReference
|
||||
*/
|
||||
@@ -60,13 +69,64 @@ export default class DocumentReference {
|
||||
.then(result => new DocumentSnapshot(this._firestore, result));
|
||||
}
|
||||
|
||||
onSnapshot(onNext: Function, onError?: Function): () => void {
|
||||
// TODO: Validation
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: DocumentListenOptions | Observer | (DocumentSnapshot) => void,
|
||||
observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void,
|
||||
onError?: (Object) => void
|
||||
) {
|
||||
let observer = {};
|
||||
let docListenOptions = {};
|
||||
// Called with: onNext, ?onError
|
||||
if (isFunction(optionsOrObserverOrOnNext)) {
|
||||
observer.next = optionsOrObserverOrOnNext;
|
||||
if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Second argument must be a valid function.');
|
||||
}
|
||||
observer.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.');
|
||||
}
|
||||
observer = optionsOrObserverOrOnNext;
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.');
|
||||
}
|
||||
} else if (optionsOrObserverOrOnNext.includeMetadataChanges) {
|
||||
docListenOptions = optionsOrObserverOrOnNext;
|
||||
// Called with: Options, onNext, ?onError
|
||||
if (isFunction(observerOrOnNextOrOnError)) {
|
||||
observer.next = observerOrOnNextOrOnError;
|
||||
if (onError && !isFunction(onError)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Third argument must be a valid function.');
|
||||
}
|
||||
observer.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 = observerOrOnNextOrOnError;
|
||||
} 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, nativeDocumentSnapshot);
|
||||
onNext(documentSnapshot);
|
||||
observer.next(documentSnapshot);
|
||||
};
|
||||
|
||||
// Listen to snapshot events
|
||||
@@ -76,16 +136,16 @@ export default class DocumentReference {
|
||||
);
|
||||
|
||||
// Listen for snapshot error events
|
||||
if (onError) {
|
||||
if (observer.error) {
|
||||
this._firestore.on(
|
||||
this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`),
|
||||
onError,
|
||||
observer.error,
|
||||
);
|
||||
}
|
||||
|
||||
// Add the native listener
|
||||
this._firestore._native
|
||||
.documentOnSnapshot(this.path, listenerId);
|
||||
.documentOnSnapshot(this.path, listenerId, docListenOptions);
|
||||
|
||||
// Return an unsubscribe method
|
||||
return this._offDocumentSnapshot.bind(this, listenerId, listener);
|
||||
@@ -96,7 +156,25 @@ export default class DocumentReference {
|
||||
.documentSet(this.path, data, writeOptions);
|
||||
}
|
||||
|
||||
update(data: Object): Promise<void> {
|
||||
update(...args: Object | string[]): Promise<void> {
|
||||
let data = {};
|
||||
if (args.length === 1) {
|
||||
if (!isObject(args[0])) {
|
||||
throw new Error('DocumentReference.update failed: If using a single argument, it must be an object.');
|
||||
}
|
||||
data = args[0];
|
||||
} else if (args.length % 2 === 1) {
|
||||
throw new Error('DocumentReference.update failed: Must have either a single object argument, or equal numbers of key/value pairs.');
|
||||
} else {
|
||||
for (let i = 0; i < args.length; i += 2) {
|
||||
const key = args[i];
|
||||
const value = args[i + 1];
|
||||
if (!isString(key)) {
|
||||
throw new Error(`DocumentReference.update failed: Argument at index ${i} must be a string`);
|
||||
}
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
return this._firestore._native
|
||||
.documentUpdate(this.path, data);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import Path from './Path';
|
||||
import QuerySnapshot from './QuerySnapshot';
|
||||
import INTERNALS from '../../internals';
|
||||
import { firestoreAutoId } from '../../utils';
|
||||
import { firestoreAutoId, isFunction, isObject } from '../../utils';
|
||||
|
||||
const DIRECTIONS = {
|
||||
ASC: 'ASCENDING',
|
||||
@@ -44,6 +43,15 @@ type QueryOptions = {
|
||||
startAt?: any[],
|
||||
}
|
||||
export type Operator = '<' | '<=' | '=' | '==' | '>' | '>=';
|
||||
type QueryListenOptions = {
|
||||
includeQueryMetadataChanges: boolean,
|
||||
includeQueryMetadataChanges: boolean,
|
||||
}
|
||||
|
||||
type Observer = {
|
||||
next: (DocumentSnapshot) => void,
|
||||
error?: (Object) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* @class Query
|
||||
@@ -116,13 +124,65 @@ export default class Query {
|
||||
this._fieldOrders, options);
|
||||
}
|
||||
|
||||
onSnapshot(onNext: () => any, onError?: () => any): () => void {
|
||||
// TODO: Validation
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void,
|
||||
observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void,
|
||||
onError?: (Object) => void,
|
||||
) {
|
||||
let observer = {};
|
||||
let queryListenOptions = {};
|
||||
// Called with: onNext, ?onError
|
||||
if (isFunction(optionsOrObserverOrOnNext)) {
|
||||
observer.next = optionsOrObserverOrOnNext;
|
||||
if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) {
|
||||
throw new Error('Query.onSnapshot failed: Second argument must be a valid function.');
|
||||
}
|
||||
observer.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('Query.onSnapshot failed: Observer.error must be a valid function.');
|
||||
}
|
||||
observer = optionsOrObserverOrOnNext;
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.');
|
||||
}
|
||||
} else if (optionsOrObserverOrOnNext.includeDocumentMetadataChanges || optionsOrObserverOrOnNext.includeQueryMetadataChanges) {
|
||||
queryListenOptions = optionsOrObserverOrOnNext;
|
||||
// Called with: Options, onNext, ?onError
|
||||
if (isFunction(observerOrOnNextOrOnError)) {
|
||||
observer.next = observerOrOnNextOrOnError;
|
||||
if (onError && !isFunction(onError)) {
|
||||
throw new Error('Query.onSnapshot failed: Third argument must be a valid function.');
|
||||
}
|
||||
observer.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('Query.onSnapshot failed: Observer.error must be a valid function.');
|
||||
}
|
||||
observer = observerOrOnNextOrOnError;
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Second argument must be a function or observer.');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: First argument must be a function, observer or options.');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Called with invalid arguments.');
|
||||
}
|
||||
|
||||
const listenerId = firestoreAutoId();
|
||||
|
||||
const listener = (nativeQuerySnapshot) => {
|
||||
const querySnapshot = new QuerySnapshot(this._firestore, this, nativeQuerySnapshot);
|
||||
onNext(querySnapshot);
|
||||
observer.next(querySnapshot);
|
||||
};
|
||||
|
||||
// Listen to snapshot events
|
||||
@@ -132,10 +192,10 @@ export default class Query {
|
||||
);
|
||||
|
||||
// Listen for snapshot error events
|
||||
if (onError) {
|
||||
if (observer.error) {
|
||||
this._firestore.on(
|
||||
this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`),
|
||||
onError,
|
||||
observer.error,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -146,7 +206,8 @@ export default class Query {
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId
|
||||
listenerId,
|
||||
queryListenOptions,
|
||||
);
|
||||
|
||||
// Return an unsubscribe method
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* WriteBatch representation wrapper
|
||||
*/
|
||||
import DocumentReference from './DocumentReference';
|
||||
import { isObject, isString } from '../../utils';
|
||||
|
||||
import type { WriteOptions } from './DocumentReference';
|
||||
|
||||
@@ -58,11 +59,27 @@ export default class WriteBatch {
|
||||
return this;
|
||||
}
|
||||
|
||||
// TODO: Update to new method signature
|
||||
update(docRef: DocumentReference, data: Object): WriteBatch {
|
||||
update(docRef: DocumentReference, ...args: Object | string[]): WriteBatch {
|
||||
// TODO: Validation
|
||||
// validate.isDocumentReference('docRef', docRef);
|
||||
// validate.isDocument('data', data, true);
|
||||
let data = {};
|
||||
if (args.length === 1) {
|
||||
if (!isObject(args[0])) {
|
||||
throw new Error('DocumentReference.update failed: If using two arguments, the second must be an object.');
|
||||
}
|
||||
data = args[0];
|
||||
} else if (args.length % 2 === 1) {
|
||||
throw new Error('DocumentReference.update failed: Must have a document reference, followed by either a single object argument, or equal numbers of key/value pairs.');
|
||||
} else {
|
||||
for (let i = 0; i < args.length; i += 2) {
|
||||
const key = args[i];
|
||||
const value = args[i + 1];
|
||||
if (!isString(key)) {
|
||||
throw new Error(`DocumentReference.update failed: Argument at index ${i + 1} must be a string`);
|
||||
}
|
||||
data[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this._writes.push({
|
||||
data,
|
||||
|
||||
Reference in New Issue
Block a user