[js][internals] _NAMESPACE & _NATIVE_MODULE static props for all modules
This commit is contained in:
parent
75c6a8f787
commit
9825226665
|
@ -26,15 +26,15 @@ export default class FirebaseApp {
|
|||
this._nativeInitialized = false;
|
||||
|
||||
// modules
|
||||
this.admob = this._staticsOrModuleInstance('admob', AdMobStatics, AdMob);
|
||||
this.auth = this._staticsOrModuleInstance('auth', AuthStatics, Auth);
|
||||
this.analytics = this._staticsOrModuleInstance('analytics', {}, Analytics);
|
||||
this.config = this._staticsOrModuleInstance('config', {}, RemoteConfig);
|
||||
this.crash = this._staticsOrModuleInstance('crash', {}, Crash);
|
||||
this.database = this._staticsOrModuleInstance('database', DatabaseStatics, Database);
|
||||
this.messaging = this._staticsOrModuleInstance('messaging', MessagingStatics, Messaging);
|
||||
this.perf = this._staticsOrModuleInstance('perf', {}, Performance);
|
||||
this.storage = this._staticsOrModuleInstance('storage', StorageStatics, Storage);
|
||||
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);
|
||||
this.messaging = this._staticsOrModuleInstance(MessagingStatics, Messaging);
|
||||
this.perf = this._staticsOrModuleInstance({}, Performance);
|
||||
this.storage = this._staticsOrModuleInstance(StorageStatics, Storage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,9 +117,9 @@ export default class FirebaseApp {
|
|||
* @return {function()}
|
||||
* @private
|
||||
*/
|
||||
_staticsOrModuleInstance(name, statics = {}, InstanceClass): Function {
|
||||
_staticsOrModuleInstance(statics = {}, InstanceClass): Function {
|
||||
const getInstance = () => {
|
||||
const _name = `_${name}`;
|
||||
const _name = `_${InstanceClass._NAMESPACE}`;
|
||||
|
||||
if (!this._namespaces[_name]) {
|
||||
this._namespaces[_name] = new InstanceClass(this);
|
||||
|
@ -129,7 +129,7 @@ export default class FirebaseApp {
|
|||
};
|
||||
|
||||
Object.assign(getInstance, statics, {
|
||||
nativeModuleExists: !!NativeModules[`RNFirebase${InstanceClass._NATIVE_MODULE || capitalizeFirstLetter(name)}`],
|
||||
nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE],
|
||||
});
|
||||
|
||||
return getInstance;
|
||||
|
|
|
@ -37,15 +37,15 @@ class FirebaseCore {
|
|||
}
|
||||
|
||||
// modules
|
||||
this.admob = this._appNamespaceOrStatics('admob', AdMobStatics, AdMob);
|
||||
this.auth = this._appNamespaceOrStatics('auth', AuthStatics, Auth);
|
||||
this.analytics = this._appNamespaceOrStatics('analytics', {}, Analytics);
|
||||
this.config = this._appNamespaceOrStatics('config', {}, RemoteConfig);
|
||||
this.crash = this._appNamespaceOrStatics('crash', {}, Crash);
|
||||
this.database = this._appNamespaceOrStatics('database', DatabaseStatics, Database);
|
||||
this.messaging = this._appNamespaceOrStatics('messaging', MessagingStatics, Messaging);
|
||||
this.perf = this._appNamespaceOrStatics('perf', DatabaseStatics, Performance);
|
||||
this.storage = this._appNamespaceOrStatics('storage', StorageStatics, Storage);
|
||||
this.admob = this._appNamespaceOrStatics(AdMobStatics, AdMob);
|
||||
this.auth = this._appNamespaceOrStatics(AuthStatics, Auth);
|
||||
this.analytics = this._appNamespaceOrStatics({}, Analytics);
|
||||
this.config = this._appNamespaceOrStatics({}, RemoteConfig);
|
||||
this.crash = this._appNamespaceOrStatics({}, Crash);
|
||||
this.database = this._appNamespaceOrStatics(DatabaseStatics, Database);
|
||||
this.messaging = this._appNamespaceOrStatics(MessagingStatics, Messaging);
|
||||
this.perf = this._appNamespaceOrStatics(DatabaseStatics, Performance);
|
||||
this.storage = this._appNamespaceOrStatics(StorageStatics, Storage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,7 +205,8 @@ class FirebaseCore {
|
|||
* @return {function(FirebaseApp=)}
|
||||
* @private
|
||||
*/
|
||||
_appNamespaceOrStatics(namespace, statics = {}, InstanceClass): Function {
|
||||
_appNamespaceOrStatics(statics = {}, InstanceClass): Function {
|
||||
const namespace = InstanceClass._NAMESPACE;
|
||||
const getNamespace = (app?: FirebaseApp) => {
|
||||
let _app = app;
|
||||
// throw an error if it's not a valid app instance
|
||||
|
@ -218,7 +219,7 @@ class FirebaseCore {
|
|||
};
|
||||
|
||||
Object.assign(getNamespace, statics, {
|
||||
nativeModuleExists: !!NativeModules[`RNFirebase${InstanceClass._NATIVE_MODULE || capitalizeFirstLetter(namespace)}`],
|
||||
nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE],
|
||||
});
|
||||
return getNamespace;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@ import NativeExpress from './NativeExpress';
|
|||
|
||||
|
||||
export default class AdMob extends ModuleBase {
|
||||
static _NATIVE_MODULE = 'AdMob';
|
||||
static _NAMESPACE = 'admob';
|
||||
static _NATIVE_MODULE = 'RNFirebaseAdMob';
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, AdMob._NATIVE_MODULE, true);
|
||||
super(firebaseApp, options, true);
|
||||
|
||||
this._initialized = false;
|
||||
this._appId = null;
|
||||
|
|
|
@ -20,8 +20,11 @@ const ReservedEventNames = [
|
|||
];
|
||||
|
||||
export default class Analytics extends ModuleBase {
|
||||
static _NAMESPACE = 'analytics';
|
||||
static _NATIVE_MODULE = 'RNFirebaseAnalytics';
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Analytics');
|
||||
super(firebaseApp, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,12 +12,15 @@ import TwitterAuthProvider from './providers/Twitter';
|
|||
import FacebookAuthProvider from './providers/Facebook';
|
||||
|
||||
export default class Auth extends ModuleBase {
|
||||
static _NAMESPACE = 'auth';
|
||||
static _NATIVE_MODULE = 'RNFirebaseAuth';
|
||||
|
||||
_user: User | null;
|
||||
_authResult: AuthResultType | null;
|
||||
authenticated: boolean;
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Auth', true);
|
||||
super(firebaseApp, options, true);
|
||||
this._user = null;
|
||||
this._authResult = null;
|
||||
this.authenticated = false;
|
||||
|
|
|
@ -7,9 +7,11 @@ import ModuleBase from './../../utils/ModuleBase';
|
|||
* @class Config
|
||||
*/
|
||||
export default class RemoteConfig extends ModuleBase {
|
||||
static _NATIVE_MODULE = 'RemoteConfig';
|
||||
static _NAMESPACE = 'config';
|
||||
static _NATIVE_MODULE = 'RNFirebaseRemoteConfig';
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, RemoteConfig._NATIVE_MODULE);
|
||||
super(firebaseApp, options);
|
||||
this.developerModeEnabled = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
import ModuleBase from './../../utils/ModuleBase';
|
||||
|
||||
export default class Crash extends ModuleBase {
|
||||
static _NAMESPACE = 'crash';
|
||||
static _NATIVE_MODULE = 'RNFirebaseCrash';
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Crash');
|
||||
super(firebaseApp, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,8 +12,11 @@ import ModuleBase from './../../utils/ModuleBase';
|
|||
* @class Database
|
||||
*/
|
||||
export default class Database extends ModuleBase {
|
||||
static _NAMESPACE = 'database';
|
||||
static _NATIVE_MODULE = 'RNFirebaseDatabase';
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Database', true);
|
||||
super(firebaseApp, options, true);
|
||||
this._transactionHandler = new TransactionHandler(this);
|
||||
|
||||
if (this._options.persistence) {
|
||||
|
|
|
@ -70,8 +70,11 @@ function finish(data) {
|
|||
* @class Messaging
|
||||
*/
|
||||
export default class Messaging extends ModuleBase {
|
||||
static _NAMESPACE = 'messaging';
|
||||
static _NATIVE_MODULE = 'RNFirebaseMessaging';
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Messaging', true);
|
||||
super(firebaseApp, options, true);
|
||||
}
|
||||
|
||||
get EVENT_TYPE() {
|
||||
|
|
|
@ -3,8 +3,11 @@ import Trace from './Trace';
|
|||
import ModuleBase from '../../utils/ModuleBase';
|
||||
|
||||
export default class PerformanceMonitoring extends ModuleBase {
|
||||
static _NAMESPACE = 'perf';
|
||||
static _NATIVE_MODULE = 'RNFirebasePerformance';
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Performance');
|
||||
super(firebaseApp, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,13 +7,15 @@ import ModuleBase from './../../utils/ModuleBase';
|
|||
const FirebaseStorage = NativeModules.RNFirebaseStorage;
|
||||
|
||||
export default class Storage extends ModuleBase {
|
||||
static _NAMESPACE = 'storage';
|
||||
static _NATIVE_MODULE = 'RNFirebaseStorage';
|
||||
/**
|
||||
*
|
||||
* @param firebaseApp
|
||||
* @param options
|
||||
*/
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
super(firebaseApp, options, 'Storage', true);
|
||||
super(firebaseApp, options, true);
|
||||
this._subscriptions = {};
|
||||
|
||||
this.addListener(
|
||||
|
|
|
@ -46,31 +46,31 @@ export default class ModuleBase {
|
|||
* @param moduleName
|
||||
* @param withEventEmitter
|
||||
*/
|
||||
constructor(firebaseApp, options, moduleName, withEventEmitter = false) {
|
||||
this._module = moduleName;
|
||||
constructor(firebaseApp, options, withEventEmitter = false) {
|
||||
this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', '');
|
||||
this._firebaseApp = firebaseApp;
|
||||
this._appName = firebaseApp._name;
|
||||
this._namespace = `${this._appName}:${this._module}`;
|
||||
this._options = Object.assign({}, DEFAULTS[moduleName] || {}, options);
|
||||
this._options = Object.assign({}, DEFAULTS[this._module] || {}, options);
|
||||
|
||||
// check if native module exists as all native
|
||||
// modules are now optionally part of build
|
||||
const nativeModule = NativeModules[`RNFirebase${moduleName}`];
|
||||
const nativeModule = NativeModules[this.constructor._NATIVE_MODULE];
|
||||
|
||||
if (!nativeModule) {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(moduleName));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(this.constructor._NATIVE_MODULE));
|
||||
}
|
||||
|
||||
// used by the modules that extend ModuleBase
|
||||
// to access their native module counterpart
|
||||
if (!MULTI_APP_MODULES.includes(moduleName.toLowerCase())) {
|
||||
if (!MULTI_APP_MODULES.includes(this._module.toLowerCase())) {
|
||||
this._native = nativeModule;
|
||||
} else {
|
||||
this._native = nativeWithApp(this._appName, nativeModule);
|
||||
}
|
||||
|
||||
if (withEventEmitter) {
|
||||
this._setupEventEmitter(nativeModule, moduleName);
|
||||
this._setupEventEmitter(nativeModule, this._module);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
import React, { Component } from 'react';
|
||||
import { View, Button, Text } from 'react-native';
|
||||
import sinon from 'sinon';
|
||||
import 'should-sinon';
|
||||
import Promise from 'bluebird';
|
||||
|
||||
import firebase from './firebase';
|
||||
import DatabaseContents from './tests/support/DatabaseContents';
|
||||
|
||||
|
||||
export default class HomeScreen extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
timeTaken: '',
|
||||
};
|
||||
}
|
||||
|
||||
clickMe = () => {
|
||||
this.setState({ timeTaken: 'Running...' });
|
||||
let start = null;
|
||||
Promise.all([
|
||||
firebase.native.database().ref('tests/types').set(DatabaseContents.DEFAULT),
|
||||
firebase.native.database().ref('tests/priority').setWithPriority({
|
||||
foo: 'bar',
|
||||
}, 666),
|
||||
firebase.native.database().ref('tests/query').set(DatabaseContents.QUERY),
|
||||
]).then(() => {
|
||||
start = Date.now();
|
||||
return Promise.each(Object.keys(DatabaseContents.DEFAULT), async (dataRef) => {
|
||||
// Setup
|
||||
const ref = firebase.native.database().ref(`tests/types/${dataRef}`);
|
||||
const currentDataValue = DatabaseContents.DEFAULT[dataRef];
|
||||
|
||||
const callbackA = sinon.spy();
|
||||
const callbackB = sinon.spy();
|
||||
|
||||
// Test
|
||||
|
||||
await new Promise((resolve) => {
|
||||
ref.on('value', (snapshot) => {
|
||||
callbackA(snapshot.val());
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve) => {
|
||||
ref.on('value', (snapshot) => {
|
||||
callbackB(snapshot.val());
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
callbackA.should.be.calledWith(currentDataValue);
|
||||
callbackA.should.be.calledOnce();
|
||||
|
||||
callbackB.should.be.calledWith(currentDataValue);
|
||||
callbackB.should.be.calledOnce();
|
||||
|
||||
const newDataValue = DatabaseContents.NEW[dataRef];
|
||||
await ref.set(newDataValue);
|
||||
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(() => resolve(), 5);
|
||||
});
|
||||
|
||||
callbackA.should.be.calledWith(newDataValue);
|
||||
callbackB.should.be.calledWith(newDataValue);
|
||||
|
||||
callbackA.should.be.calledTwice();
|
||||
callbackB.should.be.calledTwice();
|
||||
|
||||
// Tear down
|
||||
|
||||
ref.off('value');
|
||||
return Promise.resolve();
|
||||
});
|
||||
}).then(() => {
|
||||
this.setState({ timeTaken: `Took ${Date.now() - start}` });
|
||||
}).catch(console.error);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{ marginTop: 15, backgroundColor: '#000' }}>
|
||||
<Button title="Run Test" onPress={this.clickMe} />
|
||||
<Text style={{ color: '#fff' }}>{this.state.timeTaken || ''}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import { View, Text, Button } from 'react-native';
|
||||
import { View, SectionList, Text, Button } from 'react-native';
|
||||
|
||||
export default class HomeScreen extends Component {
|
||||
|
||||
|
@ -28,3 +28,132 @@ export default class HomeScreen extends Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
const sampleData = {
|
||||
somePostId1: {
|
||||
title: 'today now',
|
||||
timestamp: Date.now(),
|
||||
startOfDay: 1502838000,
|
||||
},
|
||||
|
||||
somePostId3: {
|
||||
title: 'today but older',
|
||||
timestamp: Date.now() - 10000000,
|
||||
startOfDay: 1502838000,
|
||||
},
|
||||
|
||||
somePostId4: {
|
||||
title: 'today but even older',
|
||||
timestamp: Date.now() - 60000000,
|
||||
startOfDay: 1502838000,
|
||||
},
|
||||
|
||||
somePostId2: {
|
||||
title: 'hello yesterday',
|
||||
timestamp: Date.now() - 82000000, // minus 23 hours - just to make it yesterday ;p
|
||||
startOfDay: 1502751600, // yesterday ;p
|
||||
},
|
||||
|
||||
somePostId5: {
|
||||
title: 'hello yesterday but older',
|
||||
timestamp: Date.now() - 82800000, // minus 23 hours - just to make it yesterday ;p
|
||||
startOfDay: 1502751600, // yesterday ;p
|
||||
},
|
||||
};
|
||||
|
||||
// export default class PostsScreen extends Component {
|
||||
// constructor(props) {
|
||||
// super(props);
|
||||
// this.ref = null;
|
||||
// this.state = {
|
||||
// postSections: [],
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// componentDidMount() {
|
||||
// // this.ref = firebase.database().ref('posts');
|
||||
// // this.ref.on('value', this._onPostsUpdate);
|
||||
// // just fake it to test
|
||||
// this._onPostsUpdate({
|
||||
// val() {
|
||||
// return sampleData;
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// componentWillUnmount() {
|
||||
// // always unsubscribe from realtime events when component unmounts
|
||||
// // if (this.ref) {
|
||||
// // this.ref.off('value', this._onPostsUpdate);
|
||||
// // }
|
||||
// }
|
||||
//
|
||||
// _onPostsUpdate(snapshot) {
|
||||
// const value = snapshot.val() || {};
|
||||
// const keys = Object.keys(value);
|
||||
// const sections = {};
|
||||
//
|
||||
// // we'll group them now by date
|
||||
// for (let i = 0, len = keys.length; i < len; i++) {
|
||||
// const key = keys[i];
|
||||
// const post = value[key];
|
||||
//
|
||||
// // assuming post will have a 'timestamp' field and a `startOfDay` field
|
||||
// // start of day can be calculated as above `startOfToday`
|
||||
//
|
||||
// if (!sections[post.startOfDay]) {
|
||||
// sections[post.startOfDay] = {
|
||||
// title: 'Header - I will leave this up to you', // todo today/yesterday/3 days ago etc
|
||||
// // will use this later to sort the sections so today is on top
|
||||
// key: post.startOfDay,
|
||||
// data: [],
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// const data = Object.assign({ key }, post);
|
||||
// // add a post to a specific section date
|
||||
// // we'll push/unshift depending on the date, so they' appear in order
|
||||
// if (!sections[post.startOfDay].data.length) {
|
||||
// // array is empty so nothing to compare sort, just push it
|
||||
// sections[post.startOfDay].data.push(data);
|
||||
// } else {
|
||||
// const previousTimestamp = sections[post.startOfDay].data[sections[post.startOfDay].data.length - 1].timestamp;
|
||||
// if (previousTimestamp < data.timestamp) sections[post.startOfDay].data.unshift(data);
|
||||
// else sections[post.startOfDay].data.push(data);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// this.setState({
|
||||
// postSections: Object.values(sections).sort((a, b) => a.key > b.key).reverse(),
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// _renderSectionItem = ({ item }) => {
|
||||
// // todo your custom section item component
|
||||
// // return (
|
||||
// // <EventCell
|
||||
// // userName={item.userName}
|
||||
// // postTitle={item.postTitle}
|
||||
// // />
|
||||
// // );
|
||||
//
|
||||
// return <Text>{`${item.title} - ${item.timestamp}`}</Text>;
|
||||
// };
|
||||
//
|
||||
// _renderSectionHeader = ({ section }) => {
|
||||
// // todo your custom section header
|
||||
// return (
|
||||
// <Text style={{ backgroundColor: '#000', color: '#fff' }}>{section.title}</Text>
|
||||
// );
|
||||
// };
|
||||
//
|
||||
// render() {
|
||||
// return (
|
||||
// <SectionList
|
||||
// sections={this.state.postSections}
|
||||
// renderItem={this._renderSectionItem}
|
||||
// renderSectionHeader={this._renderSectionHeader}
|
||||
// />
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue