Files
react-native-firebase/packages/firestore/lib/FirestoreDocumentReference.js
Ilja Daderko b40d44c57e Move commons into /app (#2486)
* stash

* move commons into the app
2019-08-14 13:42:08 +03:00

210 lines
5.9 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 { isObject, isString, isUndefined } from '@react-native-firebase/app/lib/common';
import NativeError from '@react-native-firebase/app/lib/internal/NativeFirebaseError';
import { parseSetOptions, parseSnapshotArgs, parseUpdateArgs } from './utils';
import { buildNativeMap, provideDocumentReferenceClass } from './utils/serialize';
// To avoid React Native require cycle warnings
let FirestoreCollectionReference = null;
export function provideCollectionReferenceClass(collectionReference) {
FirestoreCollectionReference = collectionReference;
}
let FirestoreDocumentSnapshot = null;
export function provideDocumentSnapshotClass(documentSnapshot) {
FirestoreDocumentSnapshot = documentSnapshot;
}
let _id = 0;
export default class FirestoreDocumentReference {
constructor(firestore, documentPath) {
this._firestore = firestore;
this._documentPath = documentPath;
}
get firestore() {
return this._firestore;
}
get id() {
return this._documentPath.id;
}
get parent() {
const parentPath = this._documentPath.parent();
return new FirestoreCollectionReference(this._firestore, parentPath);
}
get path() {
return this._documentPath.relativeName;
}
collection(collectionPath) {
if (!isString(collectionPath)) {
throw new Error(
"firebase.firestore().doc().collection(*) 'collectionPath' must be a string value.",
);
}
if (collectionPath === '') {
throw new Error(
"firebase.firestore().doc().collection(*) 'collectionPath' must be a non-empty string.",
);
}
const path = this._documentPath.child(collectionPath);
if (!path.isCollection) {
throw new Error(
"firebase.firestore().doc().collection(*) 'collectionPath' must point to a collection.",
);
}
return new FirestoreCollectionReference(this._firestore, path);
}
delete() {
return this._firestore.native.documentDelete(this.path);
}
get(options) {
if (!isUndefined(options) && !isObject(options)) {
throw new Error("firebase.firestore().doc().get(*) 'options' must be an object is provided.");
}
if (
options &&
options.source &&
options.source !== 'default' &&
options.source !== 'server' &&
options.source !== 'cache'
) {
throw new Error(
"firebase.firestore().doc().get(*) 'options' GetOptions.source must be one of 'default', 'server' or 'cache'.",
);
}
return this._firestore.native
.documentGet(this.path, options)
.then(data => new FirestoreDocumentSnapshot(this._firestore, data));
}
isEqual(other) {
if (!(other instanceof FirestoreDocumentReference)) {
throw new Error(
"firebase.firestore().doc().isEqual(*) 'other' expected a DocumentReference instance.",
);
}
return !(
this.path !== other.path ||
this.firestore.app.name !== other.firestore.app.name ||
this.firestore.app.options.projectId !== other.firestore.app.options.projectId
);
}
onSnapshot(...args) {
let snapshotListenOptions;
let callback;
let onNext;
let onError;
try {
const options = parseSnapshotArgs(args);
snapshotListenOptions = options.snapshotListenOptions;
callback = options.callback;
onNext = options.onNext;
onError = options.onError;
} catch (e) {
throw new Error(`firebase.firestore().doc().onSnapshot(*) ${e.message}`);
}
function handleSuccess(documentSnapshot) {
callback(documentSnapshot, null);
onNext(documentSnapshot);
}
function handleError(error) {
callback(null, error);
onError(error);
}
const listenerId = _id++;
const onSnapshotSubscription = this._firestore.emitter.addListener(
this._firestore.eventNameForApp(`firestore_document_sync_event:${listenerId}`),
event => {
if (event.body.error) {
handleError(NativeError.fromEvent(event.body.error, 'firestore'));
} else {
const documentSnapshot = new FirestoreDocumentSnapshot(
this._firestore,
event.body.snapshot,
);
handleSuccess(documentSnapshot);
}
},
);
const unsubscribe = () => {
onSnapshotSubscription.remove();
this._firestore.native.documentOffSnapshot(listenerId);
};
this._firestore.native.documentOnSnapshot(this.path, listenerId, snapshotListenOptions);
return unsubscribe;
}
set(data, options) {
if (!isObject(data)) {
throw new Error("firebase.firestore().doc().set(*) 'data' must be an object.");
}
let setOptions;
try {
setOptions = parseSetOptions(options);
} catch (e) {
throw new Error(`firebase.firestore().doc().set(_, *) ${e.message}.`);
}
return this._firestore.native.documentSet(this.path, buildNativeMap(data), setOptions);
}
update(...args) {
if (args.length === 0) {
throw new Error(
'firebase.firestore().doc().update(*) expected at least 1 argument but was called with 0 arguments.',
);
}
let data;
try {
data = parseUpdateArgs(args);
} catch (e) {
throw new Error(`firebase.firestore().doc().update(*) ${e.message}`);
}
return this._firestore.native.documentUpdate(this.path, buildNativeMap(data));
}
}
provideDocumentReferenceClass(FirestoreDocumentReference); // serialize