mirror of
https://github.com/zhigang1992/react-native-firebase.git
synced 2026-04-23 20:10:05 +08:00
more work on multiple app initialization
This commit is contained in:
@@ -2,45 +2,38 @@
|
||||
* @flow
|
||||
* Database representation wrapper
|
||||
*/
|
||||
import { NativeModules, NativeEventEmitter } from 'react-native';
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import { Base } from './../base';
|
||||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import Snapshot from './snapshot';
|
||||
import Reference from './reference';
|
||||
import TransactionHandler from './transaction';
|
||||
import { promisify, nativeSDKMissing } from './../../utils';
|
||||
|
||||
const FirebaseDatabase = NativeModules.RNFirebaseDatabase;
|
||||
const FirebaseDatabaseEvt = FirebaseDatabase && new NativeEventEmitter(FirebaseDatabase);
|
||||
import { promisify } from './../../utils';
|
||||
|
||||
/**
|
||||
* @class Database
|
||||
*/
|
||||
export default class Database extends Base {
|
||||
constructor(firebase: Object, options: Object = {}) {
|
||||
super(firebase, options);
|
||||
if (!FirebaseDatabase) {
|
||||
return nativeSDKMissing('database');
|
||||
}
|
||||
|
||||
// TODO refactor native and js - legacy code here using old fb methods
|
||||
export default class Database extends ModuleBase {
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Database', true);
|
||||
this.references = {};
|
||||
this.serverTimeOffset = 0;
|
||||
this.persistenceEnabled = false;
|
||||
this.namespace = 'firebase:database';
|
||||
this.transaction = new TransactionHandler(firebase, this, FirebaseDatabaseEvt);
|
||||
this.transaction = new TransactionHandler(this);
|
||||
|
||||
if (firebase.options.persistence === true) {
|
||||
if (options.persistence === true) {
|
||||
this._setPersistence(true);
|
||||
}
|
||||
|
||||
this.successListener = FirebaseDatabaseEvt.addListener(
|
||||
this.successListener = this._eventEmitter.addListener(
|
||||
'database_event',
|
||||
event => this._handleDatabaseEvent(event)
|
||||
event => this._handleDatabaseEvent(event),
|
||||
);
|
||||
|
||||
this.errorListener = FirebaseDatabaseEvt.addListener(
|
||||
this.errorListener = this._eventEmitter.addListener(
|
||||
'database_error',
|
||||
err => this._handleDatabaseError(err)
|
||||
err => this._handleDatabaseError(err),
|
||||
);
|
||||
|
||||
this.offsetRef = this.ref('.info/serverTimeOffset');
|
||||
@@ -63,34 +56,26 @@ export default class Database extends Base {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path
|
||||
* @param modifiersString
|
||||
* @param modifiers
|
||||
* @param eventName
|
||||
* @param cb
|
||||
* @param errorCb
|
||||
* @returns {*}
|
||||
* @param ref
|
||||
* @param listener
|
||||
*/
|
||||
on(ref: Reference, listener: DatabaseListener) {
|
||||
const { refId, path, query } = ref;
|
||||
const { listenerId, eventName } = listener;
|
||||
this.log.debug('on() : ', ref.refId, listenerId, eventName);
|
||||
this.references[refId] = ref;
|
||||
return promisify('on', FirebaseDatabase)(refId, path, query.getModifiers(), listenerId, eventName);
|
||||
return promisify('on', this._native)(refId, path, query.getModifiers(), listenerId, eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path
|
||||
* @param modifiersString
|
||||
* @param eventName
|
||||
* @param origCB
|
||||
* @returns {*}
|
||||
* @param refId
|
||||
* @param listeners
|
||||
* @param remainingListenersCount
|
||||
*/
|
||||
off(refId: number,
|
||||
// $FlowFixMe
|
||||
listeners: Array<DatabaseListener>,
|
||||
remainingListenersCount: number) {
|
||||
off(refId: number, listeners: Array<DatabaseListener>, remainingListenersCount: number) {
|
||||
this.log.debug('off() : ', refId, listeners);
|
||||
|
||||
// Delete the reference if there are no more listeners
|
||||
@@ -98,7 +83,7 @@ export default class Database extends Base {
|
||||
|
||||
if (listeners.length === 0) return Promise.resolve();
|
||||
|
||||
return promisify('off', FirebaseDatabase)(refId, listeners.map(listener => ({
|
||||
return promisify('off', this._native)(refId, listeners.map(listener => ({
|
||||
listenerId: listener.listenerId,
|
||||
eventName: listener.eventName,
|
||||
})));
|
||||
@@ -118,11 +103,11 @@ export default class Database extends Base {
|
||||
}
|
||||
|
||||
goOnline() {
|
||||
FirebaseDatabase.goOnline();
|
||||
this._native.goOnline();
|
||||
}
|
||||
|
||||
goOffline() {
|
||||
FirebaseDatabase.goOffline();
|
||||
this._native.goOffline();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +127,7 @@ export default class Database extends Base {
|
||||
if (this.persistenceEnabled !== enable) {
|
||||
this.persistenceEnabled = enable;
|
||||
this.log.debug(`${enable ? 'Enabling' : 'Disabling'} persistence.`);
|
||||
return promisify('enablePersistence', FirebaseDatabase)(enable);
|
||||
return promisify('enablePersistence', this._native)(enable);
|
||||
}
|
||||
|
||||
return Promise.reject({ status: 'Already enabled' });
|
||||
@@ -161,7 +146,7 @@ export default class Database extends Base {
|
||||
const cb = this.references[refId].refListeners[listenerId].successCallback;
|
||||
cb(new Snapshot(this.references[refId], snapshot), previousChildName);
|
||||
} else {
|
||||
FirebaseDatabase.off(refId, [{ listenerId, eventName }], () => {
|
||||
this._native.off(refId, [{ listenerId, eventName }], () => {
|
||||
this.log.debug('_handleDatabaseEvent: No JS listener registered, removed native listener', refId, listenerId, eventName);
|
||||
});
|
||||
}
|
||||
@@ -211,7 +196,7 @@ export default class Database extends Base {
|
||||
}
|
||||
|
||||
export const statics = {
|
||||
ServerValue: FirebaseDatabase ? {
|
||||
TIMESTAMP: FirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' },
|
||||
ServerValue: NativeModules.FirebaseDatabase ? {
|
||||
TIMESTAMP: NativeModules.FirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' },
|
||||
} : {},
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { ReferenceBase } from './../base';
|
||||
import ReferenceBase from './../../utils/ModuleBase';
|
||||
import Reference from './reference.js';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import Query from './query.js';
|
||||
import Snapshot from './snapshot';
|
||||
import Disconnect from './disconnect';
|
||||
import { ReferenceBase } from './../base';
|
||||
import ReferenceBase from './../../utils/ReferenceBase';
|
||||
import { promisify, isFunction, isObject, tryJSONParse, tryJSONStringify, generatePushID } from './../../utils';
|
||||
|
||||
const FirebaseDatabase = NativeModules.RNFirebaseDatabase;
|
||||
// Unique Reference ID for native events
|
||||
let refId = 1;
|
||||
|
||||
@@ -57,10 +54,11 @@ export default class Reference extends ReferenceBase {
|
||||
|
||||
refId: number;
|
||||
refListeners: { [listenerId: number]: DatabaseListener };
|
||||
database: FirebaseDatabase;
|
||||
database: Object;
|
||||
query: Query;
|
||||
|
||||
constructor(database: FirebaseDatabase, path: string, existingModifiers?: Array<DatabaseModifier>) {
|
||||
// todo logger missing as reference base no longer extends module base
|
||||
constructor(database: Object, path: string, existingModifiers?: Array<DatabaseModifier>) {
|
||||
super(path);
|
||||
this.refId = refId++;
|
||||
this.refListeners = {};
|
||||
@@ -77,7 +75,7 @@ export default class Reference extends ReferenceBase {
|
||||
*/
|
||||
keepSynced(bool: boolean) {
|
||||
const path = this.path;
|
||||
return promisify('keepSynced', FirebaseDatabase)(path, bool);
|
||||
return promisify('keepSynced', this.database._native)(path, bool);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +86,7 @@ export default class Reference extends ReferenceBase {
|
||||
set(value: any) {
|
||||
const path = this.path;
|
||||
const _value = this._serializeAnyType(value);
|
||||
return promisify('set', FirebaseDatabase)(path, _value);
|
||||
return promisify('set', this.database._native)(path, _value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +97,7 @@ export default class Reference extends ReferenceBase {
|
||||
update(val: Object) {
|
||||
const path = this.path;
|
||||
const value = this._serializeObject(val);
|
||||
return promisify('update', FirebaseDatabase)(path, value);
|
||||
return promisify('update', this.database._native)(path, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +105,7 @@ export default class Reference extends ReferenceBase {
|
||||
* @returns {*}
|
||||
*/
|
||||
remove() {
|
||||
return promisify('remove', FirebaseDatabase)(this.path);
|
||||
return promisify('remove', this.database._native)(this.path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,7 +121,7 @@ export default class Reference extends ReferenceBase {
|
||||
|
||||
const path = this.path;
|
||||
const _value = this._serializeAnyType(value);
|
||||
return promisify('push', FirebaseDatabase)(path, _value)
|
||||
return promisify('push', this.database._native)(path, _value)
|
||||
.then(({ ref }) => {
|
||||
const newRef = new Reference(this.database, ref);
|
||||
if (isFunction(onComplete)) return onComplete(null, newRef);
|
||||
@@ -244,31 +242,26 @@ export default class Reference extends ReferenceBase {
|
||||
if (arguments.length > 2 && !failureCallbackOrContext) throw new Error('Query.on failed: third argument must either be a cancel callback or a context object.');
|
||||
|
||||
this.log.debug('adding reference.on', this.refId, eventType);
|
||||
|
||||
let _failureCallback;
|
||||
let _context;
|
||||
|
||||
if (context) {
|
||||
_context = context;
|
||||
_failureCallback = failureCallbackOrContext;
|
||||
} else if (isFunction(failureCallbackOrContext)) {
|
||||
_failureCallback = failureCallbackOrContext;
|
||||
} else {
|
||||
if (isFunction(failureCallbackOrContext)) {
|
||||
_failureCallback = failureCallbackOrContext;
|
||||
} else {
|
||||
_context = failureCallbackOrContext;
|
||||
}
|
||||
_context = failureCallbackOrContext;
|
||||
}
|
||||
|
||||
if (_failureCallback) {
|
||||
_failureCallback = (error) => {
|
||||
if (error.message.startsWith('FirebaseError: permission_denied')) {
|
||||
|
||||
error.message = `permission_denied at /${this.path}: Client doesn\'t have permission to access the desired data.`
|
||||
error.message = `permission_denied at /${this.path}: Client doesn't have permission to access the desired data.`
|
||||
}
|
||||
|
||||
failureCallbackOrContext(error);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let _successCallback;
|
||||
@@ -300,7 +293,7 @@ export default class Reference extends ReferenceBase {
|
||||
* @returns {Promise.<TResult>}
|
||||
*/
|
||||
once(eventName: string = 'value', successCallback: (snapshot: Object) => void, failureCallback: (error: FirebaseError) => void) {
|
||||
return promisify('once', FirebaseDatabase)(this.refId, this.path, this.query.getModifiers(), eventName)
|
||||
return promisify('once', this.database._native)(this.refId, this.path, this.query.getModifiers(), eventName)
|
||||
.then(({ snapshot }) => new Snapshot(this, snapshot))
|
||||
.then((snapshot) => {
|
||||
if (isFunction(successCallback)) successCallback(snapshot);
|
||||
@@ -375,14 +368,10 @@ export default class Reference extends ReferenceBase {
|
||||
* @param onComplete
|
||||
* @param applyLocally
|
||||
*/
|
||||
transaction(
|
||||
transactionUpdate: Function,
|
||||
onComplete: (error: ?Error, committed: boolean, snapshot: ?Snapshot) => *,
|
||||
applyLocally: boolean = false
|
||||
) {
|
||||
transaction(transactionUpdate: Function, onComplete: (error: ?Error, committed: boolean, snapshot: ?Snapshot) => *, applyLocally: boolean = false) {
|
||||
if (!isFunction(transactionUpdate)) {
|
||||
return Promise.reject(
|
||||
new Error('Missing transactionUpdate function argument.')
|
||||
new Error('Missing transactionUpdate function argument.'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -588,7 +577,7 @@ export default class Reference extends ReferenceBase {
|
||||
*
|
||||
* {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#parent}
|
||||
*/
|
||||
get parent(): Reference|null {
|
||||
get parent(): Reference | null {
|
||||
if (this.path === '/') return null;
|
||||
return new Reference(this.database, this.path.substring(0, this.path.lastIndexOf('/')));
|
||||
}
|
||||
|
||||
@@ -2,26 +2,19 @@
|
||||
* @flow
|
||||
* Database representation wrapper
|
||||
*/
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import { Base } from './../base';
|
||||
import { generatePushID } from './../../utils';
|
||||
|
||||
const FirebaseDatabase = NativeModules.RNFirebaseDatabase;
|
||||
|
||||
/**
|
||||
* @class Database
|
||||
*/
|
||||
export default class TransactionHandler extends Base {
|
||||
constructor(firebase: Object, database: Object, FirebaseDatabaseEvt: Object) {
|
||||
super(firebase, {});
|
||||
this.transactions = {};
|
||||
this.database = database;
|
||||
this.namespace = 'firebase:database:transaction';
|
||||
|
||||
this.transactionListener = FirebaseDatabaseEvt.addListener(
|
||||
export default class TransactionHandler {
|
||||
constructor(database: Object) {
|
||||
this._transactions = {};
|
||||
this._database = database;
|
||||
this._transactionListener = this._database._eventEmitter.addListener(
|
||||
'database_transaction_event',
|
||||
event => this._handleTransactionEvent(event)
|
||||
event => this._handleTransactionEvent(event),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +33,7 @@ export default class TransactionHandler extends Base {
|
||||
) {
|
||||
const id = this._generateTransactionId();
|
||||
|
||||
this.transactions[id] = {
|
||||
this._transactions[id] = {
|
||||
id,
|
||||
reference,
|
||||
transactionUpdater,
|
||||
@@ -50,7 +43,7 @@ export default class TransactionHandler extends Base {
|
||||
started: true,
|
||||
};
|
||||
|
||||
FirebaseDatabase.startTransaction(reference.path, id, applyLocally);
|
||||
this._database._native.startTransaction(reference.path, id, applyLocally);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +56,7 @@ export default class TransactionHandler extends Base {
|
||||
* @private
|
||||
*/
|
||||
_generateTransactionId(): string {
|
||||
return generatePushID(this.database.serverTimeOffset);
|
||||
return generatePushID(this._database.serverTimeOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +89,7 @@ export default class TransactionHandler extends Base {
|
||||
const { id, value } = event;
|
||||
|
||||
try {
|
||||
const transaction = this.transactions[id];
|
||||
const transaction = this._transactions[id];
|
||||
// todo handle when transaction no longer exists on js side?
|
||||
newValue = transaction.transactionUpdater(value);
|
||||
} finally {
|
||||
@@ -106,7 +99,7 @@ export default class TransactionHandler extends Base {
|
||||
abort = true;
|
||||
}
|
||||
|
||||
FirebaseDatabase.tryCommitTransaction(id, { value: newValue, abort });
|
||||
this._database._native.tryCommitTransaction(id, { value: newValue, abort });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,14 +109,14 @@ export default class TransactionHandler extends Base {
|
||||
* @private
|
||||
*/
|
||||
_handleError(event: Object = {}) {
|
||||
const transaction = this.transactions[event.id];
|
||||
const transaction = this._transactions[event.id];
|
||||
if (transaction && !transaction.completed) {
|
||||
transaction.completed = true;
|
||||
try {
|
||||
transaction.onComplete(new Error(event.message, event.code), null);
|
||||
} finally {
|
||||
setImmediate(() => {
|
||||
delete this.transactions[event.id];
|
||||
delete this._transactions[event.id];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -135,14 +128,14 @@ export default class TransactionHandler extends Base {
|
||||
* @private
|
||||
*/
|
||||
_handleComplete(event: Object = {}) {
|
||||
const transaction = this.transactions[event.id];
|
||||
const transaction = this._transactions[event.id];
|
||||
if (transaction && !transaction.completed) {
|
||||
transaction.completed = true;
|
||||
try {
|
||||
transaction.onComplete(null, event.committed, Object.assign({}, event.snapshot));
|
||||
} finally {
|
||||
setImmediate(() => {
|
||||
delete this.transactions[event.id];
|
||||
delete this._transactions[event.id];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user