2017-06-29 16:24:34 +00:00
|
|
|
import { NativeModules } from 'react-native';
|
|
|
|
|
|
|
|
import INTERNALS from './internals';
|
2017-10-07 02:09:05 +00:00
|
|
|
import { isObject, isAndroid } from './utils';
|
2017-06-29 16:24:34 +00:00
|
|
|
|
|
|
|
import AdMob, { statics as AdMobStatics } from './modules/admob';
|
2017-07-04 12:05:19 +00:00
|
|
|
import Auth, { statics as AuthStatics } from './modules/auth';
|
2017-07-12 15:11:07 +00:00
|
|
|
import Analytics from './modules/analytics';
|
|
|
|
import Crash from './modules/crash';
|
|
|
|
import Performance from './modules/perf';
|
2017-07-04 12:05:19 +00:00
|
|
|
import RemoteConfig from './modules/config';
|
2017-06-29 16:24:34 +00:00
|
|
|
import Storage, { statics as StorageStatics } from './modules/storage';
|
|
|
|
import Database, { statics as DatabaseStatics } from './modules/database';
|
|
|
|
import Messaging, { statics as MessagingStatics } from './modules/messaging';
|
2017-09-27 14:41:25 +00:00
|
|
|
import Firestore, { statics as FirestoreStatics } from './modules/firestore';
|
2017-10-06 23:24:00 +00:00
|
|
|
import Utils, { statics as UtilsStatics } from './modules/utils';
|
2017-06-29 16:24:34 +00:00
|
|
|
|
|
|
|
const FirebaseCoreModule = NativeModules.RNFirebase;
|
|
|
|
|
|
|
|
export default class FirebaseApp {
|
|
|
|
constructor(name: string, options: Object = {}) {
|
|
|
|
this._name = name;
|
|
|
|
this._namespaces = {};
|
|
|
|
this._options = Object.assign({}, options);
|
|
|
|
|
|
|
|
// native ios/android to confirm initialized
|
2017-07-17 17:20:27 +00:00
|
|
|
this._initialized = false;
|
2017-07-18 05:02:53 +00:00
|
|
|
this._nativeInitialized = false;
|
|
|
|
|
|
|
|
// modules
|
2017-08-17 16:58:28 +00:00
|
|
|
this.admob = this._staticsOrModuleInstance(AdMobStatics, AdMob);
|
|
|
|
this.auth = this._staticsOrModuleInstance(AuthStatics, Auth);
|
|
|
|
this.analytics = this._staticsOrModuleInstance({}, Analytics);
|
|
|
|
this.config = this._staticsOrModuleInstance({}, RemoteConfig);
|
|
|
|
this.crash = this._staticsOrModuleInstance({}, Crash);
|
|
|
|
this.database = this._staticsOrModuleInstance(DatabaseStatics, Database);
|
2017-09-27 14:41:25 +00:00
|
|
|
this.firestore = this._staticsOrModuleInstance(FirestoreStatics, Firestore);
|
2017-08-17 16:58:28 +00:00
|
|
|
this.messaging = this._staticsOrModuleInstance(MessagingStatics, Messaging);
|
|
|
|
this.perf = this._staticsOrModuleInstance({}, Performance);
|
|
|
|
this.storage = this._staticsOrModuleInstance(StorageStatics, Storage);
|
2017-10-06 23:24:00 +00:00
|
|
|
this.utils = this._staticsOrModuleInstance(UtilsStatics, Utils);
|
2017-08-26 22:41:59 +00:00
|
|
|
this._extendedProps = {};
|
2017-06-29 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2017-07-17 17:20:27 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param native
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_initializeApp(native = false) {
|
|
|
|
if (native) {
|
2017-07-18 05:02:53 +00:00
|
|
|
// for apps already initialized natively that
|
|
|
|
// we have info from RN constants
|
2017-06-29 16:24:34 +00:00
|
|
|
this._initialized = true;
|
2017-07-17 17:20:27 +00:00
|
|
|
this._nativeInitialized = true;
|
2017-07-17 16:36:50 +00:00
|
|
|
} else {
|
|
|
|
FirebaseCoreModule.initializeApp(this._name, this._options, (error, result) => {
|
|
|
|
this._initialized = true;
|
2017-07-17 19:56:08 +00:00
|
|
|
INTERNALS.SharedEventEmitter.emit(`AppReady:${this._name}`, { error, result });
|
2017-07-17 16:36:50 +00:00
|
|
|
});
|
|
|
|
}
|
2017-06-29 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2017-07-17 17:20:27 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2017-06-29 16:24:34 +00:00
|
|
|
get name() {
|
2017-07-17 16:36:50 +00:00
|
|
|
if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME) {
|
|
|
|
// ios and android firebase sdk's return different
|
|
|
|
// app names - so we just return what the web sdk
|
|
|
|
// would if it was default.
|
|
|
|
return '[DEFAULT]';
|
|
|
|
}
|
|
|
|
|
2017-06-29 16:24:34 +00:00
|
|
|
return this._name;
|
|
|
|
}
|
|
|
|
|
2017-07-17 17:20:27 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2017-06-29 16:24:34 +00:00
|
|
|
get options() {
|
|
|
|
return Object.assign({}, this._options);
|
|
|
|
}
|
|
|
|
|
2017-08-26 22:41:59 +00:00
|
|
|
/**
|
2017-08-26 22:47:31 +00:00
|
|
|
* Undocumented firebase web sdk method that allows adding additional properties onto
|
|
|
|
* a firebase app instance.
|
|
|
|
*
|
|
|
|
* See: https://github.com/firebase/firebase-js-sdk/blob/master/tests/app/firebase_app.test.ts#L328
|
2017-08-26 22:41:59 +00:00
|
|
|
*
|
|
|
|
* @param props
|
|
|
|
*/
|
|
|
|
extendApp(props: Object) {
|
|
|
|
if (!isObject(props)) throw new Error(INTERNALS.ERROR_MISSING_ARG('Object', 'extendApp'));
|
|
|
|
const keys = Object.keys(props);
|
|
|
|
|
|
|
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
|
|
const key = keys[i];
|
|
|
|
|
|
|
|
if (!this._extendedProps[key] && Object.hasOwnProperty.call(this, key)) {
|
|
|
|
throw new Error(INTERNALS.ERROR_PROTECTED_PROP(key));
|
|
|
|
}
|
|
|
|
|
|
|
|
this[key] = props[key];
|
|
|
|
this._extendedProps[key] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-17 17:20:27 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @return {Promise}
|
|
|
|
*/
|
2017-06-29 16:24:34 +00:00
|
|
|
delete() {
|
2017-10-03 12:39:55 +00:00
|
|
|
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('app', 'delete'));
|
|
|
|
// TODO only the ios sdk currently supports delete, add back in when android also supports it
|
|
|
|
// if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME && this._nativeInitialized) {
|
|
|
|
// return Promise.reject(
|
|
|
|
// new Error('Unable to delete the default native firebase app instance.'),
|
|
|
|
// );
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// return FirebaseCoreModule.deleteApp(this._name);
|
2017-06-29 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-18 05:02:53 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2017-07-17 19:56:08 +00:00
|
|
|
onReady(): Promise {
|
|
|
|
if (this._initialized) return Promise.resolve(this);
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
INTERNALS.SharedEventEmitter.once(`AppReady:${this._name}`, ({ error }) => {
|
|
|
|
if (error) return reject(new Error(error)); // error is a string as it's from native
|
|
|
|
return resolve(this); // return app
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-06-29 16:24:34 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param name
|
|
|
|
* @param statics
|
|
|
|
* @param InstanceClass
|
|
|
|
* @return {function()}
|
|
|
|
* @private
|
|
|
|
*/
|
2017-08-17 16:58:28 +00:00
|
|
|
_staticsOrModuleInstance(statics = {}, InstanceClass): Function {
|
2017-06-29 16:24:34 +00:00
|
|
|
const getInstance = () => {
|
2017-08-17 16:58:28 +00:00
|
|
|
const _name = `_${InstanceClass._NAMESPACE}`;
|
2017-06-29 16:24:34 +00:00
|
|
|
|
2017-10-07 02:09:05 +00:00
|
|
|
if (isAndroid && InstanceClass._NAMESPACE !== Utils._NAMESPACE && !INTERNALS.FLAGS.checkedPlayServices) {
|
|
|
|
INTERNALS.FLAGS.checkedPlayServices = true;
|
|
|
|
this.utils().checkPlayServicesAvailability();
|
|
|
|
}
|
|
|
|
|
2017-06-29 16:24:34 +00:00
|
|
|
if (!this._namespaces[_name]) {
|
2017-10-19 13:46:02 +00:00
|
|
|
this._namespaces[_name] = new InstanceClass(this, this._options);
|
2017-06-29 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return this._namespaces[_name];
|
|
|
|
};
|
|
|
|
|
2017-08-15 16:28:51 +00:00
|
|
|
Object.assign(getInstance, statics, {
|
2017-08-17 16:58:28 +00:00
|
|
|
nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE],
|
2017-08-15 16:28:51 +00:00
|
|
|
});
|
2017-08-15 20:29:50 +00:00
|
|
|
|
2017-06-29 16:24:34 +00:00
|
|
|
return getInstance;
|
|
|
|
}
|
|
|
|
}
|