@react-native-firebase/database
Version:
React Native Firebase - The Firebase Realtime Database is a cloud-hosted database. Data is stored as JSON and synchronized in realtime to every connected client. React Native Firebase provides native integration with the Android & iOS Firebase SDKs, suppo
301 lines (262 loc) • 9.24 kB
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 {
generateDatabaseId,
isBoolean,
isFunction,
isNull,
isNumber,
isObject,
isString,
isUndefined,
isValidPath,
pathChild,
pathParent,
promiseWithOptionalCallback,
} from '@react-native-firebase/app/lib/common';
import DatabaseDataSnapshot from './DatabaseDataSnapshot';
import DatabaseOnDisconnect from './DatabaseOnDisconnect';
import DatabaseQuery, {
provideReferenceClass as provideReferenceClassForQuery,
} from './DatabaseQuery';
import DatabaseQueryModifiers from './DatabaseQueryModifiers';
import DatabaseThenableReference, {
provideReferenceClass as provideReferenceClassForThenable,
} from './DatabaseThenableReference';
const internalRefs = ['.info/connected', '.info/serverTimeOffset'];
export default class DatabaseReference extends DatabaseQuery {
constructor(database, path) {
// Validate the reference path
if (!internalRefs.includes(path) && !isValidPath(path)) {
throw new Error(
'firebase.database() Paths must be non-empty strings and can\'t contain ".", "#", "$", "[", or "]"',
);
}
super(database, path, new DatabaseQueryModifiers());
this._database = database;
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference.html#parent
*/
get parent() {
const parentPath = pathParent(this.path);
if (parentPath === null) {
return null;
}
return new DatabaseReference(this._database, parentPath);
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference.html#root
*/
get root() {
return new DatabaseReference(this._database, '/');
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference.html#child
* @param path
*/
child(path) {
if (!isString(path)) {
throw new Error("firebase.database().ref().child(*) 'path' must be a string value.");
}
return new DatabaseReference(this._database, pathChild(this.path, path));
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference.html#set
* @param value
* @param onComplete
*/
set(value, onComplete) {
if (isUndefined(value)) {
throw new Error("firebase.database().ref().set(*) 'value' must be defined.");
}
if (!isUndefined(onComplete) && !isFunction(onComplete)) {
throw new Error(
"firebase.database().ref().set(_, *) 'onComplete' must be a function if provided.",
);
}
return promiseWithOptionalCallback(this._database.native.set(this.path, { value }), onComplete);
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference.html#update
* @param values
* @param onComplete
*/
update(values, onComplete) {
if (!isObject(values)) {
throw new Error("firebase.database().ref().update(*) 'values' must be an object.");
}
const keys = Object.keys(values);
for (let i = 0; i < keys.length; i++) {
if (!isValidPath(keys[i])) {
throw new Error(
'firebase.database().update(*) \'values\' contains an invalid path. Paths must be non-empty strings and can\'t contain ".", "#", "$", "[", or "]"',
);
}
}
if (!isUndefined(onComplete) && !isFunction(onComplete)) {
throw new Error(
"firebase.database().ref().update(_, *) 'onComplete' must be a function if provided.",
);
}
return promiseWithOptionalCallback(
this._database.native.update(this.path, { values }),
onComplete,
);
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference#setwithpriority
* @param newVal
* @param newPriority
* @param onComplete
*/
setWithPriority(newVal, newPriority, onComplete) {
if (isUndefined(newVal)) {
throw new Error("firebase.database().ref().setWithPriority(*) 'newVal' must be defined.");
}
if (!isNumber(newPriority) && !isString(newPriority) && !isNull(newPriority)) {
throw new Error(
"firebase.database().ref().setWithPriority(_, *) 'newPriority' must be a number, string or null value.",
);
}
if (!isUndefined(onComplete) && !isFunction(onComplete)) {
throw new Error(
"firebase.database().ref().setWithPriority(_, _, *) 'onComplete' must be a function if provided.",
);
}
return promiseWithOptionalCallback(
this._database.native.setWithPriority(this.path, {
value: newVal,
priority: newPriority,
}),
onComplete,
);
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference#remove
* @param onComplete
*/
remove(onComplete) {
if (!isUndefined(onComplete) && !isFunction(onComplete)) {
throw new Error(
"firebase.database().ref().remove(*) 'onComplete' must be a function if provided.",
);
}
return promiseWithOptionalCallback(this._database.native.remove(this.path), onComplete);
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction
* @param transactionUpdate
* @param onComplete
* @param applyLocally
*/
transaction(transactionUpdate, onComplete, applyLocally) {
if (!isFunction(transactionUpdate)) {
throw new Error(
"firebase.database().ref().transaction(*) 'transactionUpdate' must be a function.",
);
}
if (!isUndefined(onComplete) && !isFunction(onComplete)) {
throw new Error(
"firebase.database().ref().transaction(_, *) 'onComplete' must be a function if provided.",
);
}
if (!isUndefined(applyLocally) && !isBoolean(applyLocally)) {
throw new Error(
"firebase.database().ref().transaction(_, _, *) 'applyLocally' must be a boolean value if provided.",
);
}
return new Promise((resolve, reject) => {
const onCompleteWrapper = (error, committed, snapshotData) => {
if (isFunction(onComplete)) {
if (error) {
onComplete(error, committed, null);
} else {
onComplete(null, committed, new DatabaseDataSnapshot(this, snapshotData));
}
}
if (error) {
return reject(error);
}
return resolve({
committed,
snapshot: new DatabaseDataSnapshot(this, snapshotData),
});
};
// start the transaction natively
this._database._transaction.add(this, transactionUpdate, onCompleteWrapper, applyLocally);
});
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference#setpriority
* @param priority
* @param onComplete
*/
setPriority(priority, onComplete) {
if (!isNumber(priority) && !isString(priority) && !isNull(priority)) {
throw new Error(
"firebase.database().ref().setPriority(*) 'priority' must be a number, string or null value.",
);
}
if (!isUndefined(onComplete) && !isFunction(onComplete)) {
throw new Error(
"firebase.database().ref().setPriority(_, *) 'onComplete' must be a function if provided.",
);
}
return promiseWithOptionalCallback(
this._database.native.setPriority(this.path, { priority }),
onComplete,
);
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference#push
* @param value
* @param onComplete
* @returns {DatabaseReference}
*/
push(value, onComplete) {
if (!isUndefined(onComplete) && !isFunction(onComplete)) {
throw new Error(
"firebase.database().ref().push(_, *) 'onComplete' must be a function if provided.",
);
}
const id = generateDatabaseId(this._database._serverTimeOffset);
if (isUndefined(value) || isNull(value)) {
return new DatabaseThenableReference(
this._database,
pathChild(this.path, id),
Promise.resolve(this.child(id)),
);
}
const pushRef = this.child(id);
const promise = pushRef.set(value, onComplete).then(() => pushRef);
// Prevent unhandled promise rejection if onComplete is passed
if (onComplete) {
promise.catch(() => {});
}
return new DatabaseThenableReference(this._database, pathChild(this.path, id), promise);
}
/**
* @url https://firebase.google.com/docs/reference/js/firebase.database.Reference#ondisconnect
*/
onDisconnect() {
return new DatabaseOnDisconnect(this);
}
}
// To avoid React Native require cycle warnings
provideReferenceClassForQuery(DatabaseReference);
provideReferenceClassForThenable(DatabaseReference);