2017-06-29 16:24:34 +00:00
|
|
|
/**
|
|
|
|
* @flow
|
|
|
|
*/
|
2017-07-12 14:49:33 +00:00
|
|
|
import { NativeModules } from 'react-native';
|
2017-09-25 14:38:54 +00:00
|
|
|
|
2017-06-29 16:24:34 +00:00
|
|
|
import Log from '../utils/log';
|
|
|
|
import INTERNALS from './../internals';
|
2017-07-12 14:49:33 +00:00
|
|
|
import FirebaseCore from './../firebase';
|
2017-09-25 14:38:54 +00:00
|
|
|
import FirebaseApp from '../firebase-app';
|
|
|
|
import { nativeWithApp } from './../utils';
|
2017-06-29 16:24:34 +00:00
|
|
|
|
|
|
|
const logs = {};
|
|
|
|
|
2017-07-04 12:05:19 +00:00
|
|
|
// Firebase Native SDKs that support multiple app instances
|
|
|
|
const MULTI_APP_MODULES = [
|
|
|
|
'auth',
|
|
|
|
'database',
|
|
|
|
'storage',
|
|
|
|
];
|
|
|
|
|
2017-07-12 14:49:33 +00:00
|
|
|
const NATIVE_MODULE_EVENTS = {
|
|
|
|
Storage: [
|
|
|
|
'storage_event',
|
|
|
|
'storage_error',
|
|
|
|
],
|
|
|
|
Auth: [
|
2017-09-21 16:11:17 +00:00
|
|
|
'auth_state_changed',
|
2017-09-25 14:58:49 +00:00
|
|
|
'phone_auth_state_changed',
|
2017-07-12 14:49:33 +00:00
|
|
|
],
|
2017-07-30 06:34:41 +00:00
|
|
|
Database: [
|
|
|
|
'database_transaction_event',
|
2017-08-05 21:00:06 +00:00
|
|
|
// 'database_server_offset', // TODO
|
2017-07-30 06:34:41 +00:00
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
const DEFAULTS = {
|
|
|
|
Database: {
|
|
|
|
persistence: false,
|
|
|
|
},
|
2017-07-12 14:49:33 +00:00
|
|
|
};
|
|
|
|
|
2017-06-29 16:24:34 +00:00
|
|
|
export default class ModuleBase {
|
2017-09-25 14:38:54 +00:00
|
|
|
_native: Object;
|
|
|
|
_module: string;
|
|
|
|
_options: Object;
|
|
|
|
_appName: string;
|
|
|
|
_namespace: string;
|
|
|
|
_firebaseApp: Object;
|
|
|
|
_eventEmitter: Object;
|
|
|
|
static _NAMESPACE: string;
|
|
|
|
static _NATIVE_MODULE: string;
|
|
|
|
|
2017-07-18 05:04:12 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param firebaseApp
|
|
|
|
* @param options
|
|
|
|
* @param withEventEmitter
|
|
|
|
*/
|
2017-09-25 14:38:54 +00:00
|
|
|
constructor(firebaseApp: Object, options: Object, withEventEmitter: boolean = false) {
|
2017-08-17 16:58:28 +00:00
|
|
|
this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', '');
|
2017-06-29 16:24:34 +00:00
|
|
|
this._firebaseApp = firebaseApp;
|
2017-07-17 16:36:50 +00:00
|
|
|
this._appName = firebaseApp._name;
|
2017-06-29 16:24:34 +00:00
|
|
|
this._namespace = `${this._appName}:${this._module}`;
|
2017-08-17 16:58:28 +00:00
|
|
|
this._options = Object.assign({}, DEFAULTS[this._module] || {}, options);
|
2017-06-29 16:24:34 +00:00
|
|
|
|
2017-07-12 14:49:33 +00:00
|
|
|
// check if native module exists as all native
|
|
|
|
// modules are now optionally part of build
|
2017-08-17 16:58:28 +00:00
|
|
|
const nativeModule = NativeModules[this.constructor._NATIVE_MODULE];
|
2017-06-29 16:24:34 +00:00
|
|
|
|
|
|
|
if (!nativeModule) {
|
2017-08-18 20:05:47 +00:00
|
|
|
throw new Error(
|
|
|
|
INTERNALS.STRINGS.ERROR_MISSING_MODULE(
|
|
|
|
this.constructor._NAMESPACE,
|
|
|
|
this.constructor._NATIVE_MODULE,
|
|
|
|
),
|
|
|
|
);
|
2017-06-29 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2017-07-12 14:49:33 +00:00
|
|
|
// used by the modules that extend ModuleBase
|
|
|
|
// to access their native module counterpart
|
2017-08-17 16:58:28 +00:00
|
|
|
if (!MULTI_APP_MODULES.includes(this._module.toLowerCase())) {
|
2017-07-04 12:05:19 +00:00
|
|
|
this._native = nativeModule;
|
|
|
|
} else {
|
|
|
|
this._native = nativeWithApp(this._appName, nativeModule);
|
|
|
|
}
|
|
|
|
|
2017-06-30 16:23:32 +00:00
|
|
|
if (withEventEmitter) {
|
2017-08-17 16:58:28 +00:00
|
|
|
this._setupEventEmitter(nativeModule, this._module);
|
2017-06-30 16:23:32 +00:00
|
|
|
}
|
2017-06-29 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2017-07-12 14:49:33 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param nativeModule
|
|
|
|
* @param moduleName
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_setupEventEmitter(nativeModule, moduleName) {
|
2017-07-18 05:04:12 +00:00
|
|
|
this._eventEmitter = FirebaseCore._getOrSetNativeEmitter(`${this._appName}-${this._module}`, nativeModule);
|
2017-07-12 14:49:33 +00:00
|
|
|
const events = NATIVE_MODULE_EVENTS[moduleName];
|
|
|
|
|
|
|
|
if (events && events.length) {
|
|
|
|
for (let i = 0, len = events.length; i < len; i++) {
|
|
|
|
FirebaseCore._subscribeForDistribution(events[i], this._eventEmitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param eventName
|
|
|
|
* @return {string}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_getAppEventName(eventName) {
|
|
|
|
return `${this._appName}-${eventName}`;
|
|
|
|
}
|
|
|
|
|
2017-06-29 16:24:34 +00:00
|
|
|
/**
|
|
|
|
* Returns the FirebaseApp instance for current module
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2017-09-25 14:38:54 +00:00
|
|
|
get app(): FirebaseApp {
|
2017-06-29 16:24:34 +00:00
|
|
|
return this._firebaseApp;
|
|
|
|
}
|
|
|
|
|
|
|
|
get log(): Log {
|
|
|
|
if (logs[this._namespace]) return logs[this._namespace];
|
|
|
|
return logs[this._namespace] = Log.createLogger(
|
|
|
|
`🔥 ${this._namespace.toUpperCase()}`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Proxy functions to shared event emitter instance
|
|
|
|
* https://github.com/facebook/react-native/blob/master/Libraries/EventEmitter/EventEmitter.js
|
|
|
|
*/
|
2017-09-25 14:38:54 +00:00
|
|
|
get sharedEventEmitter(): Object {
|
2017-06-29 16:24:34 +00:00
|
|
|
return INTERNALS.SharedEventEmitter;
|
|
|
|
}
|
|
|
|
|
2017-09-25 14:38:54 +00:00
|
|
|
get addListener(): Function {
|
2017-06-29 16:24:34 +00:00
|
|
|
return INTERNALS.SharedEventEmitter.addListener.bind(INTERNALS.SharedEventEmitter);
|
|
|
|
}
|
|
|
|
|
2017-09-25 14:38:54 +00:00
|
|
|
get once(): Function {
|
2017-08-19 04:22:07 +00:00
|
|
|
return INTERNALS.SharedEventEmitter.once.bind(INTERNALS.SharedEventEmitter);
|
|
|
|
}
|
|
|
|
|
2017-09-25 14:38:54 +00:00
|
|
|
get on(): Function {
|
2017-06-29 16:24:34 +00:00
|
|
|
return INTERNALS.SharedEventEmitter.addListener.bind(INTERNALS.SharedEventEmitter);
|
|
|
|
}
|
|
|
|
|
2017-09-25 14:38:54 +00:00
|
|
|
get emit(): Function {
|
2017-06-29 16:24:34 +00:00
|
|
|
return INTERNALS.SharedEventEmitter.emit.bind(INTERNALS.SharedEventEmitter);
|
|
|
|
}
|
|
|
|
|
2017-09-25 14:38:54 +00:00
|
|
|
get listeners(): Function {
|
2017-06-29 16:24:34 +00:00
|
|
|
return INTERNALS.SharedEventEmitter.listeners.bind(INTERNALS.SharedEventEmitter);
|
|
|
|
}
|
|
|
|
|
|
|
|
hasListeners(eventType: string): Boolean {
|
|
|
|
const subscriptions = INTERNALS.SharedEventEmitter._subscriber.getSubscriptionsForType(eventType);
|
|
|
|
return subscriptions && subscriptions.length;
|
|
|
|
}
|
|
|
|
|
2017-09-25 14:38:54 +00:00
|
|
|
get removeListener(): Function {
|
2017-06-29 16:24:34 +00:00
|
|
|
return INTERNALS.SharedEventEmitter.removeListener.bind(INTERNALS.SharedEventEmitter);
|
|
|
|
}
|
|
|
|
|
2017-09-25 14:38:54 +00:00
|
|
|
get removeAllListeners(): Function {
|
2017-06-29 16:24:34 +00:00
|
|
|
return INTERNALS.SharedEventEmitter.removeAllListeners.bind(INTERNALS.SharedEventEmitter);
|
|
|
|
}
|
|
|
|
}
|