Files
react-native-firebase/packages/firestore/lib/FirestoreQuerySnapshot.js
2019-07-12 14:12:53 +01:00

137 lines
3.8 KiB
JavaScript

/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { isBoolean, isFunction, isObject, isUndefined } from '@react-native-firebase/common';
import FirestoreDocumentChange from './FirestoreDocumentChange';
import FirestoreDocumentSnapshot from './FirestoreDocumentSnapshot';
import FirestoreSnapshotMetadata from './FirestoreSnapshotMetadata';
export default class FirestoreQuerySnapshot {
constructor(firestore, query, nativeData) {
this._query = query;
this._source = nativeData.source;
this._excludesMetadataChanges = nativeData.excludesMetadataChanges;
this._changes = nativeData.changes.map($ => new FirestoreDocumentChange(firestore, $));
this._docs = nativeData.documents.map($ => new FirestoreDocumentSnapshot(firestore, $));
this._metadata = new FirestoreSnapshotMetadata(nativeData.metadata);
}
get docs() {
return this._docs;
}
get empty() {
return this._docs.length === 0;
}
get metadata() {
return this._metadata;
}
get query() {
return this._query;
}
get size() {
return this._docs.length;
}
docChanges(options) {
if (!isUndefined(options) && !isObject(options)) {
throw new Error(
`firebase.firestore() QuerySnapshot.docChanges(*) 'options' expected an object.`,
);
}
let includeMetaDataChanges = false;
if (options) {
if (!isBoolean(options.includeMetadataChanges)) {
throw new Error(
`firebase.firestore() QuerySnapshot.docChanges(*) 'options.includeMetadataChanges' expected a boolean.`,
);
}
includeMetaDataChanges = options.includeMetadataChanges;
}
// A get query should always return the document changes from native
if (this._source === 'get') {
return this._changes;
}
if (includeMetaDataChanges && this._excludesMetadataChanges) {
throw new Error(
`firebase.firestore() QuerySnapshot.docChanges() To include metadata changes with your document changes, you must also pass { includeMetadataChanges:true } to onSnapshot().`,
);
}
return this._changes.filter($ => {
// Remove all changes that have come from metadata changes list
if (!includeMetaDataChanges) {
return $._isMetadataChange === false;
}
return true;
});
}
forEach(callback, thisArg) {
if (!isFunction(callback)) {
throw new Error(
`firebase.firestore() QuerySnapshot.forEach(*) 'callback' expected a function.`,
);
}
const cb = thisArg ? callback.bind(thisArg) : callback;
for (let i = 0; i < this._docs.length; i++) {
cb(this._docs[i], i);
}
}
isEqual(other) {
if (!(other instanceof FirestoreQuerySnapshot)) {
throw new Error(
`firebase.firestore() QuerySnapshot.isEqual(*) 'other' expected a QuerySnapshot instance.`,
);
}
// Simple checks first
if (
this.empty !== other.empty ||
this.size !== other.size ||
!this.metadata.isEqual(other.metadata)
) {
return false;
}
// Expensive check
// Each doc must be in order & have the same data
for (let i = 0; i < this.docs.length; i++) {
const thisDoc = this.docs[i];
const otherDoc = other.docs[i];
if (!thisDoc.isEqual(otherDoc)) {
return false;
}
}
return true;
}
}