mirror of
https://github.com/zhigang1992/react-native-firebase.git
synced 2026-01-12 22:50:20 +08:00
[v6] Implement Remote Config (#1896)
This commit is contained in:
committed by
Mike Diarmid
parent
8ef8038c94
commit
fb7109e52a
14
CHANGELOG.md
14
CHANGELOG.md
@@ -158,6 +158,20 @@ await analytics().setUserId('12345678');
|
||||
- [NEW] Added support for `firebase.perf.Trace.removeMetric(metricName: string)`
|
||||
- [NEW] Added support for `firebase.perf.Trace.getMetrics(): { [key: string]: number }`
|
||||
|
||||
|
||||
## Remote Config (config)
|
||||
|
||||
- [NEW] Added a new `fetchAndActivate` method - this fetches the config and activate it without the need to call `activateFetch()` separately
|
||||
- [NEW] Added a new `getConfigSettings` method - this provides the following properties; `lastFetchTime`, `lastFetchStatus` & `isDeveloperModeEnabled`
|
||||
- [NEW] Added a new `setConfigSettings` method - this allows setting `isDeveloperModeEnabled`, replaces the `enableDeveloperMode` method
|
||||
- [NEW] Added a new `getValuesByKeysPrefix` method - this will retrieve all values where the key matches the prefix provided, this saves having to call `getKeysByPrefix` and then `getValues` separately
|
||||
- [BREAKING] `setDefaultsFromResource` now returns a Promise that resolves when completed, this will reject with code `config/resouce_not_found` if the file could not be found
|
||||
- [BREAKING] `setDefaultsFromResource` now expects a resource file name for Android to match iOS, formerly this required a resource id (something you would not have in RN as this was generated at build time by Android)
|
||||
- We're writing up a guide for this on the new documentation website, showing how to use the plist/xml defaults files on each platform
|
||||
- [BREAKING] `enableDeveloperMode` has been removed, you can now use `setConfigSettings({ isDeveloperModeEnabled: boolean })` instead
|
||||
- [BREAKING] `setDefaults` now returns a Promise that resolves when completed
|
||||
|
||||
|
||||
## Messaging
|
||||
|
||||
- [NEW] Support `setAutoInitEnabled(enabled: boolean)` - this is useful for opt-in first flows
|
||||
|
||||
2389
docs/typedoc.json
2389
docs/typedoc.json
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -15,18 +15,18 @@
|
||||
"tests:packager:chrome": "cd tests && react-native start --platforms ios,android",
|
||||
"tests:packager:jet": "REACT_DEBUGGER='echo nope' cd tests && react-native start",
|
||||
"tests:packager:jet-reset-cache": "REACT_DEBUGGER='echo nope' cd tests && react-native start --reset-cache",
|
||||
"tests:android:build": "cd tests && detox build --configuration android.emu.debug",
|
||||
"tests:android:build-release": "cd tests && detox build --configuration android.emu.release",
|
||||
"tests:android:test": "cd tests && detox test --configuration android.emu.debug",
|
||||
"tests:android:test-reuse": "cd tests && detox test --configuration android.emu.debug --reuse",
|
||||
"tests:android:build": "cd tests && ./node_modules/.bin/detox build --configuration android.emu.debug",
|
||||
"tests:android:build-release": "cd tests && ./node_modules/.bin/detox build --configuration android.emu.release",
|
||||
"tests:android:test": "cd tests && ./node_modules/.bin/detox test --configuration android.emu.debug",
|
||||
"tests:android:test-reuse": "cd tests && ./node_modules/.bin/detox test --configuration android.emu.debug --reuse",
|
||||
"tests:android:test-cover": "cd tests && nyc ./node_modules/.bin/detox test --configuration android.emu.debug",
|
||||
"tests:android:test-cover-reuse": "cd tests && nyc detox test --configuration android.emu.debug --reuse",
|
||||
"tests:ios:build": "cd tests && detox build --configuration ios.sim.debug",
|
||||
"tests:ios:build-release": "cd tests && detox build --configuration ios.sim.release",
|
||||
"tests:ios:test": "cd tests && detox test --configuration ios.sim.debug --loglevel warn",
|
||||
"tests:ios:test-reuse": "cd tests && detox test --configuration ios.sim.debug --reuse --loglevel warn",
|
||||
"tests:android:test-cover-reuse": "cd tests && nyc ./node_modules/.bin/detox test --configuration android.emu.debug --reuse",
|
||||
"tests:ios:build": "cd tests && ./node_modules/.bin/detox build --configuration ios.sim.debug",
|
||||
"tests:ios:build-release": "cd tests && ./node_modules/.bin/detox build --configuration ios.sim.release",
|
||||
"tests:ios:test": "cd tests && ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn",
|
||||
"tests:ios:test-reuse": "cd tests && ./node_modules/.bin/detox test --configuration ios.sim.debug --reuse --loglevel warn",
|
||||
"tests:ios:test-cover": "cd tests && nyc ./node_modules/.bin/detox test --configuration ios.sim.debug",
|
||||
"tests:ios:test-cover-reuse": "cd tests && nyc detox test --configuration ios.sim.debug --reuse --loglevel warn",
|
||||
"tests:ios:test-cover-reuse": "cd tests && nyc ./node_modules/.bin/detox test --configuration ios.sim.debug --reuse --loglevel warn",
|
||||
"tests:ios:pod:install": "cd tests && cd ios && rm -rf ReactNativeFirebaseDemo.xcworkspace && pod install && cd ..",
|
||||
"npm:version:release:patch": "echo '!!🔴!! RELEASE !!🔴!!' && lerna version patch --exact --force-publish=*",
|
||||
"npm:version:release:minor": "echo '!!🔴!! RELEASE !!🔴!!' && lerna version minor --exact --force-publish=*",
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-analytics:${ReactNative.ext.getVersion("firebase", "analytics")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/analytics'
|
||||
rootProject.name = '@react-native-firebase_analytics'
|
||||
|
||||
@@ -17,6 +17,7 @@ package io.invertase.firebase.analytics;
|
||||
*
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
@@ -38,6 +39,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
super(reactContext, TAG);
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ReactMethod
|
||||
public void logEvent(String name, @Nullable ReadableMap params, Promise promise) {
|
||||
try {
|
||||
@@ -48,6 +50,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ReactMethod
|
||||
public void setAnalyticsCollectionEnabled(Boolean enabled, Promise promise) {
|
||||
try {
|
||||
@@ -63,6 +66,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
@@ -81,6 +85,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ReactMethod
|
||||
public void setMinimumSessionDuration(double milliseconds, Promise promise) {
|
||||
try {
|
||||
@@ -91,6 +96,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ReactMethod
|
||||
public void setSessionTimeoutDuration(double milliseconds, Promise promise) {
|
||||
try {
|
||||
@@ -101,6 +107,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ReactMethod
|
||||
public void setUserId(String id, Promise promise) {
|
||||
try {
|
||||
@@ -111,6 +118,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ReactMethod
|
||||
public void setUserProperty(String name, String value, Promise promise) {
|
||||
try {
|
||||
@@ -125,7 +133,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
public void setUserProperties(ReadableMap properties, Promise promise) {
|
||||
try {
|
||||
ReadableMapKeySetIterator iterator = properties.keySetIterator();
|
||||
FirebaseAnalytics firebaseAnalytics = FirebaseAnalytics.getInstance(getContext());
|
||||
@SuppressLint("MissingPermission") FirebaseAnalytics firebaseAnalytics = FirebaseAnalytics.getInstance(getContext());
|
||||
|
||||
while (iterator.hasNextKey()) {
|
||||
String name = iterator.nextKey();
|
||||
@@ -139,6 +147,7 @@ public class ReactNativeFirebaseAnalyticsModule extends ReactNativeFirebaseModul
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@ReactMethod
|
||||
public void resetAnalyticsData(Promise promise) {
|
||||
try {
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/app'
|
||||
rootProject.name = '@react-native-firebase_app'
|
||||
|
||||
@@ -30,6 +30,8 @@ import com.facebook.react.bridge.WritableMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.invertase.firebase.interfaces.ContextProvider;
|
||||
|
||||
public class ReactNativeFirebaseModule extends ReactContextBaseJavaModule implements ContextProvider {
|
||||
@@ -72,10 +74,17 @@ public class ReactNativeFirebaseModule extends ReactContextBaseJavaModule implem
|
||||
}
|
||||
|
||||
public void rejectPromiseWithExceptionMap(Promise promise, Exception exception) {
|
||||
// TODO hook into crashlytics - report as handled exception?
|
||||
promise.reject(exception, getExceptionMap(exception));
|
||||
}
|
||||
|
||||
public void rejectPromiseWithCodeAndMessage(Promise promise, String code, String message) {
|
||||
WritableMap userInfoMap = Arguments.createMap();
|
||||
userInfoMap.putString("code", code);
|
||||
userInfoMap.putString("message", message);
|
||||
promise.reject(code, message, userInfoMap);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "RNFB" + moduleName + "Module";
|
||||
|
||||
@@ -72,16 +72,11 @@ NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT";
|
||||
|
||||
NSError *error = [NSError errorWithDomain:RNFBErrorDomain code:666 userInfo:userInfo];
|
||||
|
||||
// TODO hook into crashlytics - report as handled exception?
|
||||
|
||||
reject(exception.name, exception.reason, error);
|
||||
}
|
||||
|
||||
+ (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject userInfo:(NSMutableDictionary *)userInfo; {
|
||||
NSError *error = [NSError errorWithDomain:RNFBErrorDomain code:666 userInfo:userInfo];
|
||||
|
||||
// TODO hook into crashlytics - report as handled exception?
|
||||
|
||||
reject(userInfo[@"code"], userInfo[@"message"], error);
|
||||
}
|
||||
@end
|
||||
@@ -28,9 +28,9 @@ end
|
||||
|
||||
def react_native_firebase!(config = {})
|
||||
react_native_firebase_path = config.fetch(:react_native_firebase_path, '../node_modules/@react-native-firebase')
|
||||
known_firebase_modules = %w(app analytics crashlytics fiam functions firestore iid invites perf utils)
|
||||
known_firebase_modules = %w(app analytics config crashlytics fiam functions firestore iid invites perf utils)
|
||||
|
||||
# TODO: validate versions / set pod versions
|
||||
# TODO(salakar): validate versions / set pod versions
|
||||
app_package = JSON.parse(File.read("#{react_native_firebase_path}/#{known_firebase_modules[0]}/package.json"))
|
||||
app_package_version = app_package['version']
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-auth:${ReactNative.ext.getVersion("firebase", "auth")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/auth'
|
||||
rootProject.name = '@react-native-firebase_auth'
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-config:${ReactNative.ext.getVersion("firebase", "config")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/config'
|
||||
rootProject.name = '@react-native-firebase_config'
|
||||
|
||||
@@ -17,24 +17,247 @@ package io.invertase.firebase.config;
|
||||
*
|
||||
*/
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigFetchThrottledException;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigInfo;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import io.invertase.firebase.common.ReactNativeFirebaseModule;
|
||||
|
||||
import static com.google.firebase.remoteconfig.FirebaseRemoteConfig.LAST_FETCH_STATUS_FAILURE;
|
||||
import static com.google.firebase.remoteconfig.FirebaseRemoteConfig.LAST_FETCH_STATUS_NO_FETCH_YET;
|
||||
import static com.google.firebase.remoteconfig.FirebaseRemoteConfig.LAST_FETCH_STATUS_SUCCESS;
|
||||
import static com.google.firebase.remoteconfig.FirebaseRemoteConfig.LAST_FETCH_STATUS_THROTTLED;
|
||||
|
||||
public class ReactNativeFirebaseConfigModule extends ReactNativeFirebaseModule {
|
||||
private static final String TAG = "Config";
|
||||
private static final String STRING_VALUE = "stringValue";
|
||||
private static final String BOOL_VALUE = "boolValue";
|
||||
private static final String NUMBER_VALUE = "numberValue";
|
||||
private static final String SOURCE = "source";
|
||||
|
||||
ReactNativeFirebaseConfigModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext, TAG);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void activateFetched(Promise promise) {
|
||||
boolean activated = FirebaseRemoteConfig.getInstance().activateFetched();
|
||||
promise.resolve(activated);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void fetch(double cacheExpirationSeconds, boolean activate, Promise promise) {
|
||||
Task<Void> fetchTask;
|
||||
|
||||
if (cacheExpirationSeconds == -1) {
|
||||
fetchTask = FirebaseRemoteConfig.getInstance().fetch((long) cacheExpirationSeconds);
|
||||
} else {
|
||||
fetchTask = FirebaseRemoteConfig.getInstance().fetch();
|
||||
}
|
||||
|
||||
fetchTask.addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
if (activate) {
|
||||
promise.resolve(FirebaseRemoteConfig.getInstance().activateFetched());
|
||||
} else {
|
||||
promise.resolve(null);
|
||||
}
|
||||
} else {
|
||||
if (task.getException() instanceof FirebaseRemoteConfigFetchThrottledException) {
|
||||
rejectPromiseWithCodeAndMessage(
|
||||
promise,
|
||||
"throttled",
|
||||
"fetch() operation cannot be completed successfully, due to throttling."
|
||||
);
|
||||
} else {
|
||||
rejectPromiseWithCodeAndMessage(
|
||||
promise,
|
||||
"failure",
|
||||
"fetch() operation cannot be completed successfully."
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getConfigSettings(Promise promise) {
|
||||
WritableMap configSettingsMap = Arguments.createMap();
|
||||
FirebaseRemoteConfigInfo remoteConfigInfo = FirebaseRemoteConfig.getInstance().getInfo();
|
||||
FirebaseRemoteConfigSettings remoteConfigSettings = remoteConfigInfo.getConfigSettings();
|
||||
|
||||
configSettingsMap.putDouble("lastFetchTime", remoteConfigInfo.getFetchTimeMillis());
|
||||
configSettingsMap.putString(
|
||||
"lastFetchStatus",
|
||||
lastFetchStatusToString(remoteConfigInfo.getLastFetchStatus())
|
||||
);
|
||||
configSettingsMap.putBoolean(
|
||||
"isDeveloperModeEnabled",
|
||||
remoteConfigSettings.isDeveloperModeEnabled()
|
||||
);
|
||||
|
||||
promise.resolve(configSettingsMap);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setConfigSettings(ReadableMap configSettings, Promise promise) {
|
||||
FirebaseRemoteConfigSettings.Builder configSettingsBuilder = new FirebaseRemoteConfigSettings.Builder();
|
||||
configSettingsBuilder.setDeveloperModeEnabled(configSettings.getBoolean("isDeveloperModeEnabled"));
|
||||
FirebaseRemoteConfig.getInstance().setConfigSettings(configSettingsBuilder.build());
|
||||
getConfigSettings(promise);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setDefaults(ReadableMap defaults, Promise promise) {
|
||||
FirebaseRemoteConfig.getInstance().setDefaults(defaults.toHashMap());
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setDefaultsFromResource(String resourceName, Promise promise) {
|
||||
int resourceId = getXmlResourceIdByName(resourceName);
|
||||
XmlResourceParser xmlResourceParser = null;
|
||||
|
||||
try {
|
||||
xmlResourceParser = getApplicationContext().getResources().getXml(resourceId);
|
||||
} catch (Resources.NotFoundException nfe) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
if (xmlResourceParser != null) {
|
||||
FirebaseRemoteConfig.getInstance().setDefaults(resourceId);
|
||||
promise.resolve(null);
|
||||
} else {
|
||||
rejectPromiseWithCodeAndMessage(
|
||||
promise,
|
||||
"resource_not_found",
|
||||
"The specified resource name was not found."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private int getXmlResourceIdByName(String name) {
|
||||
String packageName = getApplicationContext().getPackageName();
|
||||
return getApplicationContext().getResources().getIdentifier(name, "xml", packageName);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getValuesByKeysPrefix(String prefix, Promise promise) {
|
||||
Set<String> keys = FirebaseRemoteConfig.getInstance().getKeysByPrefix(prefix);
|
||||
WritableMap writableMap = Arguments.createMap();
|
||||
|
||||
for (String key : keys) {
|
||||
FirebaseRemoteConfigValue configValue = FirebaseRemoteConfig.getInstance().getValue(key);
|
||||
writableMap.putMap(key, convertRemoteConfigValue(configValue));
|
||||
}
|
||||
|
||||
promise.resolve(writableMap);
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void getKeysByPrefix(String prefix, Promise promise) {
|
||||
WritableArray keysByPrefix = Arguments.createArray();
|
||||
|
||||
Set<String> keys = FirebaseRemoteConfig.getInstance().getKeysByPrefix(prefix);
|
||||
|
||||
for (String key : keys) {
|
||||
keysByPrefix.pushString(key);
|
||||
}
|
||||
|
||||
promise.resolve(keysByPrefix);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getValue(String key, Promise promise) {
|
||||
FirebaseRemoteConfigValue configValue = FirebaseRemoteConfig.getInstance().getValue(key);
|
||||
promise.resolve(convertRemoteConfigValue(configValue));
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getValues(ReadableArray keys, Promise promise) {
|
||||
WritableArray valuesArray = Arguments.createArray();
|
||||
ArrayList<Object> keysList = keys.toArrayList();
|
||||
|
||||
for (Object key : keysList) {
|
||||
|
||||
FirebaseRemoteConfigValue configValue = FirebaseRemoteConfig
|
||||
.getInstance()
|
||||
.getValue((String) key);
|
||||
|
||||
valuesArray.pushMap(convertRemoteConfigValue(configValue));
|
||||
}
|
||||
|
||||
promise.resolve(valuesArray);
|
||||
}
|
||||
|
||||
private WritableMap convertRemoteConfigValue(FirebaseRemoteConfigValue value) {
|
||||
WritableMap map = Arguments.createMap();
|
||||
|
||||
map.putString(STRING_VALUE, value.asString());
|
||||
|
||||
try {
|
||||
boolean booleanValue = value.asBoolean();
|
||||
map.putBoolean(BOOL_VALUE, booleanValue);
|
||||
} catch (Exception e) {
|
||||
map.putNull(BOOL_VALUE);
|
||||
}
|
||||
|
||||
try {
|
||||
double numberValue = value.asDouble();
|
||||
map.putDouble(NUMBER_VALUE, numberValue);
|
||||
} catch (Exception e) {
|
||||
map.putNull(NUMBER_VALUE);
|
||||
}
|
||||
|
||||
switch (value.getSource()) {
|
||||
case FirebaseRemoteConfig.VALUE_SOURCE_DEFAULT:
|
||||
map.putString(SOURCE, "default");
|
||||
break;
|
||||
case FirebaseRemoteConfig.VALUE_SOURCE_REMOTE:
|
||||
map.putString(SOURCE, "remote");
|
||||
break;
|
||||
default:
|
||||
map.putString(SOURCE, "static");
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
private String lastFetchStatusToString(int fetchStatus) {
|
||||
String status = "unknown";
|
||||
switch (fetchStatus) {
|
||||
case LAST_FETCH_STATUS_SUCCESS:
|
||||
status = "success";
|
||||
break;
|
||||
case LAST_FETCH_STATUS_FAILURE:
|
||||
status = "failure";
|
||||
break;
|
||||
case LAST_FETCH_STATUS_NO_FETCH_YET:
|
||||
status = "no_fetch_yet";
|
||||
break;
|
||||
case LAST_FETCH_STATUS_THROTTLED:
|
||||
status = "throttled";
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,23 +22,333 @@ describe('config()', () => {
|
||||
should.exist(app.config);
|
||||
app.config().app.should.equal(app);
|
||||
});
|
||||
});
|
||||
|
||||
// removing as pending if module.options.hasMultiAppSupport = true
|
||||
xit('supports multiple apps', async () => {
|
||||
firebase.config().app.name.should.equal('[DEFAULT]');
|
||||
|
||||
firebase
|
||||
.config(firebase.app('secondaryFromNative'))
|
||||
.app.name.should.equal('secondaryFromNative');
|
||||
|
||||
firebase
|
||||
.app('secondaryFromNative')
|
||||
.config()
|
||||
.app.name.should.equal('secondaryFromNative');
|
||||
describe('fetch()', () => {
|
||||
it('with expiration provided', () => firebase.config().fetch(0));
|
||||
it('without expiration provided', () => firebase.config().fetch());
|
||||
it('it throws if expiration is not a number', () => {
|
||||
try {
|
||||
firebase.config().fetch('foo');
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be a number value');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('aMethod()', () => {
|
||||
// TODO
|
||||
describe('fetchAndActivate()', () => {
|
||||
it('returns true/false if activated', async () => {
|
||||
const activated = await firebase.config().fetchAndActivate(0);
|
||||
activated.should.be.a.Boolean();
|
||||
});
|
||||
it('with expiration provided', () => firebase.config().fetchAndActivate(0));
|
||||
it('without expiration provided', () => firebase.config().fetchAndActivate());
|
||||
it('it throws if expiration is not a number', () => {
|
||||
try {
|
||||
firebase.config().fetchAndActivate('foo');
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be a number value');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('activateFetched()', () => {
|
||||
it('with expiration provided', async () => {
|
||||
await firebase.config().fetch(0);
|
||||
const activated = await firebase.config().activateFetched();
|
||||
activated.should.be.a.Boolean();
|
||||
});
|
||||
|
||||
it('without expiration provided', async () => {
|
||||
await firebase.config().fetch();
|
||||
const activated = await firebase.config().activateFetched();
|
||||
activated.should.be.a.Boolean();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getConfigSettings()', () => {
|
||||
it('gets settings', async () => {
|
||||
const settings = await firebase.config().getConfigSettings();
|
||||
settings.isDeveloperModeEnabled.should.be.a.Boolean();
|
||||
settings.isDeveloperModeEnabled.should.equal(false);
|
||||
settings.lastFetchStatus.should.be.a.String();
|
||||
settings.lastFetchStatus.should.equal('success');
|
||||
settings.lastFetchTime.should.be.a.Number();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setConfigSettings()', () => {
|
||||
it('isDeveloperModeEnabled sets correctly', async () => {
|
||||
const settingsBefore = await firebase.config().getConfigSettings();
|
||||
settingsBefore.isDeveloperModeEnabled.should.equal(false);
|
||||
settingsBefore.isDeveloperModeEnabled.should.be.a.Boolean();
|
||||
|
||||
await firebase.config().setConfigSettings({ isDeveloperModeEnabled: true });
|
||||
|
||||
const settingsAfter = await firebase.config().getConfigSettings();
|
||||
settingsAfter.isDeveloperModeEnabled.should.equal(true);
|
||||
settingsAfter.isDeveloperModeEnabled.should.be.a.Boolean();
|
||||
|
||||
await firebase.config().setConfigSettings({ isDeveloperModeEnabled: false });
|
||||
});
|
||||
|
||||
it('returns the new config settings', async () => {
|
||||
const settings = await firebase.config().setConfigSettings({ isDeveloperModeEnabled: false });
|
||||
settings.isDeveloperModeEnabled.should.be.a.Boolean();
|
||||
settings.isDeveloperModeEnabled.should.equal(false);
|
||||
settings.lastFetchStatus.should.be.a.String();
|
||||
settings.lastFetchStatus.should.equal('success');
|
||||
settings.lastFetchTime.should.be.a.Number();
|
||||
});
|
||||
|
||||
it('it throws if no args', async () => {
|
||||
try {
|
||||
await firebase.config().setConfigSettings();
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be an object');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('it throws if object does not contain isDeveloperModeEnabled key', async () => {
|
||||
try {
|
||||
await firebase.config().setConfigSettings({});
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql(`'isDeveloperModeEnabled' key`);
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('it throws if isDeveloperModeEnabled key is not a boolean', async () => {
|
||||
try {
|
||||
await firebase.config().setConfigSettings({ isDeveloperModeEnabled: 'potato' });
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql(
|
||||
`'settings.isDeveloperModeEnabled' must be a boolean value`,
|
||||
);
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('getKeysByPrefix()', () => {
|
||||
it('should return an object of all available values if no key prefix provided', async () => {
|
||||
const config = await firebase.config().getValuesByKeysPrefix();
|
||||
config.number.value.should.equal(1337);
|
||||
config.number.source.should.equal('remote');
|
||||
// firebase console stores as a string
|
||||
config.float.value.should.equal(123.456);
|
||||
config.float.source.should.equal('remote');
|
||||
});
|
||||
|
||||
it('should return an object filtered by prefixed keys', async () => {
|
||||
const config = await firebase.config().getValuesByKeysPrefix('prefix_');
|
||||
Object.keys(config).length.should.equal(3);
|
||||
config.prefix_1.value.should.equal(1);
|
||||
config.prefix_1.source.should.equal('remote');
|
||||
});
|
||||
|
||||
it('it throws if prefix is not a string', async () => {
|
||||
try {
|
||||
await firebase.config().getValuesByKeysPrefix(1337);
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be a string value');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('getKeysByPrefix()', () => {
|
||||
it('should return an array of all available keys if no prefix provided', async () => {
|
||||
const keys = await firebase.config().getKeysByPrefix();
|
||||
keys.length.should.equal(9);
|
||||
keys[0].should.be.a.String();
|
||||
});
|
||||
|
||||
it('should return an array of prefixed keys', async () => {
|
||||
const keys = await firebase.config().getKeysByPrefix('prefix_');
|
||||
keys.length.should.equal(3);
|
||||
keys[0].should.be.a.String();
|
||||
});
|
||||
|
||||
it('it throws if prefix is not a string', () => {
|
||||
try {
|
||||
firebase.config().getKeysByPrefix(1337);
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be a string value');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('setDefaults()', () => {
|
||||
it('sets default values from key values object', async () => {
|
||||
await firebase.config().setDefaults({
|
||||
some_key: 'I do not exist',
|
||||
some_key_1: 1337,
|
||||
some_key_2: true,
|
||||
});
|
||||
|
||||
await firebase.config().fetch(0);
|
||||
|
||||
const values = await firebase.config().getValues(['some_key', 'some_key_1', 'some_key_2']);
|
||||
|
||||
values.some_key.value.should.equal('I do not exist');
|
||||
values.some_key_1.value.should.equal(1337);
|
||||
should.equal(values.some_key_2.value, true);
|
||||
|
||||
values.some_key.source.should.equal('default');
|
||||
values.some_key_1.source.should.equal('default');
|
||||
values.some_key_2.source.should.equal('default');
|
||||
});
|
||||
|
||||
it('it throws if defaults object not provided', () => {
|
||||
try {
|
||||
firebase.config().setDefaults();
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be an object');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('it throws if defaults arg is not an object', () => {
|
||||
try {
|
||||
firebase.config().setDefaults(1337);
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be an object');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('setDefaultsFromResource()', () => {
|
||||
it('sets defaults from remote_config_resource_test file', async () => {
|
||||
await Utils.sleep(10000);
|
||||
await firebase.config().setDefaultsFromResource('remote_config_resource_test');
|
||||
const config = await firebase.config().getValues(['company']);
|
||||
config.company.source.should.equal('default');
|
||||
config.company.value.should.equal('invertase');
|
||||
});
|
||||
|
||||
it('it rejects if resource not found', async () => {
|
||||
const [error] = await A2A(firebase.config().setDefaultsFromResource('i_do_not_exist'));
|
||||
if (!error) throw new Error('Did not reject');
|
||||
error.code.should.equal('config/resource_not_found');
|
||||
error.message.should.containEql('was not found');
|
||||
});
|
||||
|
||||
it('it throws if resourceName is not a string', () => {
|
||||
try {
|
||||
firebase.config().setDefaultsFromResource(1337);
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be a string value');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('getValue()', () => {
|
||||
it('returns a value for the specified key', async () => {
|
||||
const configValue = await firebase.config().getValue('string');
|
||||
configValue.source.should.equal('remote');
|
||||
configValue.value.should.equal('invertase');
|
||||
});
|
||||
|
||||
it('errors if no key provided', async () => {
|
||||
try {
|
||||
await firebase.config().getValue();
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be a string');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('errors if key not a string', async () => {
|
||||
try {
|
||||
await firebase.config().getValue(1234);
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be a string');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('getValues()', () => {
|
||||
it('returns undefined for non existent keys', async () => {
|
||||
const config = await firebase.config().getValues(['boopy', 'shoopy']);
|
||||
should.equal(config.boopy.value, undefined);
|
||||
should.equal(config.boopy.source, 'static');
|
||||
should.equal(config.shoopy.value, undefined);
|
||||
should.equal(config.shoopy.source, 'static');
|
||||
});
|
||||
|
||||
it('get multiple values by an array of keys', async () => {
|
||||
const config = await firebase.config().getValues(['bool', 'string', 'number']);
|
||||
|
||||
config.should.be.a.Object();
|
||||
config.should.have.keys('bool', 'string', 'number');
|
||||
|
||||
const boolValue = config.bool.value;
|
||||
const stringValue = config.string.value;
|
||||
const numberValue = config.number.value;
|
||||
|
||||
boolValue.should.be.equal(true);
|
||||
stringValue.should.be.equal('invertase');
|
||||
numberValue.should.be.equal(1337);
|
||||
});
|
||||
|
||||
it('errors if no args', async () => {
|
||||
try {
|
||||
await firebase.config().getValues();
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be an non empty array');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('errors if not an array', async () => {
|
||||
try {
|
||||
await firebase.config().getValues({ foo: 'bar' });
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be an non empty array');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('errors if array is empty', async () => {
|
||||
try {
|
||||
await firebase.config().getValues([]);
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be an non empty array');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
it('errors if array values are not strings', async () => {
|
||||
try {
|
||||
await firebase.config().getValues([1, 2, 3]);
|
||||
return Promise.reject(new Error('Did not throw'));
|
||||
} catch (error) {
|
||||
error.message.should.containEql('must be an array of strings');
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ Pod::Spec.new do |s|
|
||||
s.source_files = 'RNFBConfig/**/*.{h,m}'
|
||||
s.dependency 'React'
|
||||
s.dependency 'Firebase/Core', '~> 5.17.0'
|
||||
s.dependency 'Firebase/RemoteConfig', '~> 5.17.0'
|
||||
s.dependency 'RNFBApp'
|
||||
s.static_framework = true
|
||||
end
|
||||
|
||||
@@ -16,13 +16,59 @@
|
||||
*/
|
||||
|
||||
#import <React/RCTUtils.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <Firebase/Firebase.h>
|
||||
|
||||
#import "RNFBConfigModule.h"
|
||||
#import "RNFBApp/RNFBSharedUtils.h"
|
||||
#import "RNFBSharedUtils.h"
|
||||
|
||||
|
||||
@implementation RNFBConfigModule
|
||||
#pragma mark -
|
||||
# pragma mark Converters
|
||||
|
||||
NSString *convertFIRRemoteConfigFetchStatusToNSString(FIRRemoteConfigFetchStatus value) {
|
||||
switch (value) {
|
||||
case FIRRemoteConfigFetchStatusNoFetchYet:
|
||||
return @"no_fetch_yet";
|
||||
case FIRRemoteConfigFetchStatusSuccess:
|
||||
return @"success";
|
||||
case FIRRemoteConfigFetchStatusThrottled:
|
||||
return @"throttled";
|
||||
case FIRRemoteConfigFetchStatusFailure:
|
||||
return @"failure";
|
||||
default:
|
||||
return @"unknown";
|
||||
}
|
||||
}
|
||||
|
||||
NSString *convertFIRRemoteConfigFetchStatusToNSStringDescription(FIRRemoteConfigFetchStatus value) {
|
||||
switch (value) {
|
||||
case FIRRemoteConfigFetchStatusThrottled:
|
||||
return @"fetch() operation cannot be completed successfully, due to throttling.";
|
||||
case FIRRemoteConfigFetchStatusNoFetchYet:
|
||||
default:
|
||||
return @"fetch() operation cannot be completed successfully.";
|
||||
}
|
||||
}
|
||||
|
||||
NSString *convertFIRRemoteConfigSourceToNSString(FIRRemoteConfigSource value) {
|
||||
switch (value) {
|
||||
case FIRRemoteConfigSourceDefault:
|
||||
return @"default";
|
||||
case FIRRemoteConfigSourceRemote:
|
||||
return @"remote";
|
||||
case FIRRemoteConfigSourceStatic:
|
||||
return @"static";
|
||||
default:
|
||||
return @"unknown";
|
||||
}
|
||||
}
|
||||
|
||||
NSDictionary *convertFIRRemoteConfigValueToNSDictionary(FIRRemoteConfigValue *value) {
|
||||
return @{@"stringValue": (id) value.stringValue ?: [NSNull null], @"numberValue": (id) value.numberValue ?: [NSNull null], @"boolValue": @(value.boolValue), @"source": convertFIRRemoteConfigSourceToNSString(value.source)};
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Module Setup
|
||||
|
||||
@@ -32,7 +78,162 @@
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Firebase Config Methods
|
||||
|
||||
RCT_EXPORT_METHOD(fetch:
|
||||
(nonnull
|
||||
NSNumber *)expirationDuration
|
||||
activate: (BOOL) activate
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
FIRRemoteConfigFetchCompletion completionHandler = ^(FIRRemoteConfigFetchStatus status, NSError *__nullable error) {
|
||||
if (error) {
|
||||
[RNFBSharedUtils rejectPromiseWithUserInfo:reject userInfo:[@{@"code": convertFIRRemoteConfigFetchStatusToNSString(status), @"message": convertFIRRemoteConfigFetchStatusToNSStringDescription(status)} mutableCopy]];
|
||||
} else {
|
||||
if (activate) {
|
||||
resolve(@([[FIRRemoteConfig remoteConfig] activateFetched]));
|
||||
} else {
|
||||
resolve([NSNull null]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (expirationDuration == @(-1)) {
|
||||
[[FIRRemoteConfig remoteConfig] fetchWithExpirationDuration:expirationDuration.doubleValue completionHandler:completionHandler];
|
||||
} else {
|
||||
[[FIRRemoteConfig remoteConfig] fetchWithCompletionHandler:completionHandler];
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(activateFetched:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
BOOL status = [[FIRRemoteConfig remoteConfig] activateFetched];
|
||||
resolve(@(status));
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getConfigSettings:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
resolve([self getConfigSettings]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getValue:
|
||||
(NSString *) key
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRRemoteConfigValue *value = [[FIRRemoteConfig remoteConfig] configValueForKey:key];
|
||||
resolve(convertFIRRemoteConfigValueToNSDictionary(value));
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getValues:
|
||||
(NSArray *) keys
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
NSMutableArray *valuesArray = [[NSMutableArray alloc] init];
|
||||
|
||||
for (NSString *key in keys) {
|
||||
FIRRemoteConfigValue *value = [[FIRRemoteConfig remoteConfig] configValueForKey:key];
|
||||
[valuesArray addObject:convertFIRRemoteConfigValueToNSDictionary(value)];
|
||||
}
|
||||
|
||||
resolve(valuesArray);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setConfigSettings:
|
||||
(NSDictionary *) configSettings
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] initWithDeveloperModeEnabled:[configSettings[@"isDeveloperModeEnabled"] boolValue]];
|
||||
[FIRRemoteConfig remoteConfig].configSettings = remoteConfigSettings;
|
||||
resolve([self getConfigSettings]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getKeysByPrefix:
|
||||
(NSString *) prefix
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
NSSet *keys = [[FIRRemoteConfig remoteConfig] keysWithPrefix:prefix];
|
||||
|
||||
NSMutableArray *keysArray = [[NSMutableArray alloc] init];
|
||||
for (NSString *key in keys) {
|
||||
[keysArray addObject:key];
|
||||
}
|
||||
|
||||
resolve(keysArray);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getValuesByKeysPrefix:
|
||||
(NSString *) prefix
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
NSSet *keys = [[FIRRemoteConfig remoteConfig] keysWithPrefix:prefix];
|
||||
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionary];
|
||||
|
||||
for (NSString *key in keys) {
|
||||
FIRRemoteConfigValue *value = [[FIRRemoteConfig remoteConfig] configValueForKey:key];
|
||||
mutableDictionary[key] = convertFIRRemoteConfigValueToNSDictionary(value);
|
||||
}
|
||||
|
||||
resolve(mutableDictionary);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setDefaults:
|
||||
(NSDictionary *) defaults
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject
|
||||
) {
|
||||
[[FIRRemoteConfig remoteConfig] setDefaults:defaults];
|
||||
resolve([NSNull null]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setDefaultsFromResource:
|
||||
(NSString *) fileName
|
||||
resolver:
|
||||
(RCTPromiseResolveBlock) resolve
|
||||
rejecter:
|
||||
(RCTPromiseRejectBlock) reject) {
|
||||
if ([[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"] != nil) {
|
||||
[[FIRRemoteConfig remoteConfig] setDefaultsFromPlistFileName:fileName];
|
||||
resolve([NSNull null]);
|
||||
} else {
|
||||
[RNFBSharedUtils rejectPromiseWithUserInfo:reject userInfo:[@{@"code": @"resource_not_found", @"message": @"The specified resource name was not found."} mutableCopy]];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Internal Helper Methods
|
||||
|
||||
|
||||
- (NSDictionary *)getConfigSettings {
|
||||
FIRRemoteConfig *remoteConfig = [FIRRemoteConfig remoteConfig];
|
||||
BOOL isDeveloperModeEnabled = [RCTConvert BOOL:@([remoteConfig configSettings].isDeveloperModeEnabled)];
|
||||
NSString *lastFetchStatus = convertFIRRemoteConfigFetchStatusToNSString(remoteConfig.lastFetchStatus);
|
||||
NSDate *lastFetchTime = remoteConfig.lastFetchTime;
|
||||
return @{
|
||||
@"isDeveloperModeEnabled": @(isDeveloperModeEnabled),
|
||||
@"lastFetchTime": @(round([lastFetchTime timeIntervalSince1970])),
|
||||
@"lastFetchStatus": lastFetchStatus
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
136
packages/config/lib/index.d.ts
vendored
136
packages/config/lib/index.d.ts
vendored
@@ -22,15 +22,129 @@ import {
|
||||
} from '@react-native-firebase/app-types';
|
||||
|
||||
/**
|
||||
* Config
|
||||
* Firebase Remote Config is a cloud service that lets you change the behavior and appearance of your
|
||||
* app without requiring users to download an app update. When using Remote Config, you create in-app default
|
||||
* values that control the behavior and appearance of your app.
|
||||
*
|
||||
* @firebase config
|
||||
*/
|
||||
export namespace Config {
|
||||
export interface Statics {}
|
||||
|
||||
export interface Module extends ReactNativeFirebaseModule {
|
||||
/**
|
||||
* An Interface representing a Remote Config value
|
||||
*/
|
||||
export interface ConfigValue {
|
||||
/**
|
||||
* Where the value was retrieved from
|
||||
*/
|
||||
source: 'remote' | 'default' | 'static';
|
||||
|
||||
/**
|
||||
* The value
|
||||
*/
|
||||
value: undefined | number | boolean | string;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing multiple Config Values
|
||||
*/
|
||||
export interface ConfigValues {
|
||||
[key: string]: ConfigValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing settable config settings.
|
||||
*/
|
||||
export interface ConfigSettingsWrite {
|
||||
isDeveloperModeEnabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing readable config settings.
|
||||
*/
|
||||
export interface ConfigSettingsRead {
|
||||
lastFetchTime: number;
|
||||
isDeveloperModeEnabled: boolean;
|
||||
lastFetchStatus: 'success' | 'failure' | 'no_fetch_yet' | 'throttled';
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing a Config Defaults object.
|
||||
*/
|
||||
export interface ConfigDefaults {
|
||||
[key: string]: number | string | boolean;
|
||||
}
|
||||
|
||||
export interface Module extends ReactNativeFirebaseModule {
|
||||
/**
|
||||
* Moves fetched data to the apps active config.
|
||||
* Always successfully resolves with a boolean value of whether the fetched config was moved successfully.
|
||||
*/
|
||||
activateFetched(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Fetches the remote config data from Firebase, defined in the dashboard. If duration is defined (seconds), data will be locally cached for this duration.
|
||||
*
|
||||
* @param cacheExpirationSeconds Duration in seconds to cache the data for. To force a cache use a duration of 0.
|
||||
*/
|
||||
fetch(cacheExpirationSeconds?: number): Promise<null>;
|
||||
|
||||
/**
|
||||
* Fetches the remote config data from Firebase, defined in the dashboard. If duration is defined (seconds), data will be locally cached for this duration.
|
||||
*
|
||||
* Once fetching is completely this method immediately calls activateFetched on native and returns a boolean value of activation status.
|
||||
*
|
||||
* @param cacheExpirationSeconds Duration in seconds to cache the data for. To force a cache use a duration of 0.
|
||||
*/
|
||||
fetchAndActivate(cacheExpirationSeconds?: number): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Retrieve the configuration settings and status for Remote Config.
|
||||
*/
|
||||
getConfigSettings(): Promise<ConfigSettingsRead>;
|
||||
|
||||
/**
|
||||
* Returns all keys matching the prefix as an array. If no prefix is defined all keys are returned.
|
||||
*
|
||||
* @param prefix
|
||||
*/
|
||||
getKeysByPrefix(prefix?: string): Promise<string[]>;
|
||||
|
||||
/**
|
||||
* Returns all config values for the keys matching the prefix provided. In no prefix is provided all values are returned.
|
||||
*
|
||||
* @param prefix
|
||||
*/
|
||||
getValuesByKeysPrefix(prefix?: string): Promise<ConfigValues>;
|
||||
|
||||
/**
|
||||
* Gets a ConfigValue by key.
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
getValue(key: string): Promise<ConfigValue>;
|
||||
|
||||
/**
|
||||
* Set the Remote Config settings, specifically the `isDeveloperModeEnabled` flag.
|
||||
*/
|
||||
setConfigSettings(configSettings: ConfigSettingsWrite): Promise<ConfigSettingsRead>;
|
||||
|
||||
/**
|
||||
* Sets default values for the app to use when accessing values.
|
||||
* Any data fetched and activated will override any default values. Any values in the defaults but not on Firebase will be untouched.
|
||||
*
|
||||
*/
|
||||
setDefaults(defaults: ConfigDefaults): Promise<null>;
|
||||
|
||||
/**
|
||||
* Sets the default values from a resource file.
|
||||
* On iOS this is a plist file and on Android this is an XML defaultsMap file.
|
||||
* TODO(ehesp): insert link to guide here somehow?
|
||||
*
|
||||
* @param resourceName The plist/xml file name with no extension.
|
||||
*/
|
||||
setDefaultsFromResource(resourceName: string): Promise<null>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +162,7 @@ declare module '@react-native-firebase/config' {
|
||||
*/
|
||||
export const firebase = FirebaseNamespaceExport;
|
||||
|
||||
const ConfigDefaultExport: ReactNativeFirebaseModuleAndStatics<
|
||||
Config.Module,
|
||||
Config.Statics
|
||||
>;
|
||||
const ConfigDefaultExport: ReactNativeFirebaseModuleAndStatics<Config.Module, Config.Statics>;
|
||||
/**
|
||||
* @example
|
||||
* ```js
|
||||
@@ -68,17 +179,18 @@ declare module '@react-native-firebase/config' {
|
||||
declare module '@react-native-firebase/app-types' {
|
||||
interface ReactNativeFirebaseNamespace {
|
||||
/**
|
||||
* Config
|
||||
* Firebase Remote Config is a cloud service that lets you change the behavior and appearance of your
|
||||
* app without requiring users to download an app update. When using Remote Config, you create in-app default
|
||||
* values that control the behavior and appearance of your app.
|
||||
*/
|
||||
config: ReactNativeFirebaseModuleAndStatics<
|
||||
Config.Module,
|
||||
Config.Statics
|
||||
>;
|
||||
config: ReactNativeFirebaseModuleAndStatics<Config.Module, Config.Statics>;
|
||||
}
|
||||
|
||||
interface FirebaseApp {
|
||||
/**
|
||||
* Config
|
||||
* Firebase Remote Config is a cloud service that lets you change the behavior and appearance of your
|
||||
* app without requiring users to download an app update. When using Remote Config, you create in-app default
|
||||
* values that control the behavior and appearance of your app.
|
||||
*/
|
||||
config(): Config.Module;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,15 @@ import {
|
||||
FirebaseModule,
|
||||
getFirebaseRoot,
|
||||
} from '@react-native-firebase/app/lib/internal';
|
||||
|
||||
import {
|
||||
hasOwnProperty,
|
||||
isNumber,
|
||||
isString,
|
||||
isBoolean,
|
||||
isArray,
|
||||
isUndefined,
|
||||
isObject,
|
||||
} from '@react-native-firebase/common';
|
||||
import version from './version';
|
||||
|
||||
const statics = {};
|
||||
@@ -29,8 +37,221 @@ const namespace = 'config';
|
||||
|
||||
const nativeModuleName = 'RNFBConfigModule';
|
||||
|
||||
class FirebaseConfigModule extends FirebaseModule {
|
||||
/**
|
||||
*
|
||||
* @param nativeValue
|
||||
* @returns {*}
|
||||
*/
|
||||
function nativeValueToJS(nativeValue) {
|
||||
return {
|
||||
source: nativeValue.source,
|
||||
get value() {
|
||||
const { boolValue, stringValue, numberValue } = nativeValue;
|
||||
|
||||
// undefined
|
||||
if (boolValue === false && numberValue === 0 && !stringValue.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// boolean
|
||||
if (
|
||||
boolValue !== null &&
|
||||
(stringValue === 'true' || stringValue === 'false' || stringValue === null)
|
||||
) {
|
||||
return boolValue;
|
||||
}
|
||||
|
||||
// number
|
||||
if (
|
||||
numberValue !== null &&
|
||||
numberValue !== undefined &&
|
||||
(stringValue == null || stringValue === '' || numberValue.toString() === stringValue || parseInt(stringValue, 10) === numberValue)
|
||||
) {
|
||||
return numberValue;
|
||||
}
|
||||
|
||||
// string
|
||||
return stringValue;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
class FirebaseConfigModule extends FirebaseModule {
|
||||
/**
|
||||
* Activates the Fetched Config, so that the fetched key-values take effect.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
activateFetched() {
|
||||
return this.native.activateFetched();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches parameter values for your app.
|
||||
|
||||
* @param {number} cacheExpirationSeconds
|
||||
* @returns {Promise}
|
||||
*/
|
||||
fetch(cacheExpirationSeconds) {
|
||||
if (!isUndefined(cacheExpirationSeconds) && !isNumber(cacheExpirationSeconds)) {
|
||||
throw new Error(
|
||||
`firebase.config().fetch(): 'cacheExpirationSeconds' must be a number value.`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.native.fetch(cacheExpirationSeconds !== undefined ? cacheExpirationSeconds : -1, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO(salakar) return boolean always?
|
||||
* @param cacheExpirationSeconds
|
||||
* @returns {Promise|never|Promise<Response>}
|
||||
*/
|
||||
fetchAndActivate(cacheExpirationSeconds) {
|
||||
if (!isUndefined(cacheExpirationSeconds) && !isNumber(cacheExpirationSeconds)) {
|
||||
throw new Error(
|
||||
`firebase.config().fetchAndActivate(): 'cacheExpirationSeconds' must be a number value.`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.native.fetch(cacheExpirationSeconds !== undefined ? cacheExpirationSeconds : -1, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns FirebaseRemoteConfig singleton
|
||||
* lastFetchTime,
|
||||
* lastFetchStatus.
|
||||
* isDeveloperModeEnabled
|
||||
* @returns {Object}
|
||||
*/
|
||||
getConfigSettings() {
|
||||
return this.native.getConfigSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of keys that start with the given prefix.
|
||||
*
|
||||
* @param {string} prefix
|
||||
* @returns {string[]}
|
||||
*/
|
||||
getKeysByPrefix(prefix) {
|
||||
if (!isUndefined(prefix) && !isString(prefix)) {
|
||||
throw new Error(`firebase.config().getKeysByPrefix(): 'prefix' must be a string value.`);
|
||||
}
|
||||
|
||||
return this.native.getKeysByPrefix(prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param prefix
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async getValuesByKeysPrefix(prefix) {
|
||||
if (!isUndefined(prefix) && !isString(prefix)) {
|
||||
throw new Error(
|
||||
`firebase.config().getValuesByKeysPrefix(): 'prefix' must be a string value.`,
|
||||
);
|
||||
}
|
||||
|
||||
const output = {};
|
||||
const entries = Object.entries(await this.native.getValuesByKeysPrefix(prefix));
|
||||
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const [key, value] = entries[i];
|
||||
output[key] = nativeValueToJS(value);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the FirebaseRemoteConfigValue corresponding to the specified key.
|
||||
*
|
||||
* @param {string} key
|
||||
*/
|
||||
async getValue(key) {
|
||||
if (!isString(key)) {
|
||||
throw new Error(`firebase.config().getValue(): 'key' must be a string value.`);
|
||||
}
|
||||
|
||||
return nativeValueToJS(await this.native.getValue(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the FirebaseRemoteConfigValue array corresponding to the specified keys.
|
||||
*
|
||||
* @param keys
|
||||
*/
|
||||
async getValues(keys) {
|
||||
if (!isArray(keys) || !keys.length) {
|
||||
throw new Error(`firebase.config().getValues(): 'keys' must be an non empty array.`);
|
||||
}
|
||||
|
||||
if (!isString(keys[0])) {
|
||||
throw new Error(`firebase.config().getValues(): 'keys' must be an array of strings.`);
|
||||
}
|
||||
|
||||
const valuesObject = {};
|
||||
const keyValues = await this.native.getValues(keys);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
valuesObject[key] = nativeValueToJS(keyValues[i]);
|
||||
}
|
||||
|
||||
return valuesObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the settings for the FirebaseRemoteConfig object's operations,
|
||||
* such as turning the developer mode on.
|
||||
* @param {object} settings
|
||||
* @description Android & iOS
|
||||
*/
|
||||
setConfigSettings(settings = {}) {
|
||||
if (!isObject(settings) || !hasOwnProperty(settings, 'isDeveloperModeEnabled')) {
|
||||
throw new Error(
|
||||
`firebase.config().setConfigSettings(): 'settings' must be an object with a 'isDeveloperModeEnabled' key.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isBoolean(settings.isDeveloperModeEnabled)) {
|
||||
throw new Error(
|
||||
`firebase.config().setConfigSettings(): 'settings.isDeveloperModeEnabled' must be a boolean value.`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.native.setConfigSettings(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets defaults.
|
||||
*
|
||||
* @param {object} defaults
|
||||
*/
|
||||
setDefaults(defaults) {
|
||||
if (!isObject(defaults)) {
|
||||
throw new Error(
|
||||
`firebase.config().setDefaults(): 'defaults' must be an object.`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.native.setDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets defaults based on resource.
|
||||
* @param {string} resourceName
|
||||
*/
|
||||
setDefaultsFromResource(resourceName) {
|
||||
if (!isString(resourceName)) {
|
||||
throw new Error(
|
||||
`firebase.config().setDefaultsFromResource(): 'resourceName' must be a string value.`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.native.setDefaultsFromResource(resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
// import { SDK_VERSION } from '@react-native-firebase/config';
|
||||
|
||||
@@ -20,8 +20,120 @@ import type { ReactNativeFirebaseModule } from '@react-native-firebase/app-types
|
||||
|
||||
export interface Statics {}
|
||||
|
||||
export interface Module extends ReactNativeFirebaseModule {
|
||||
/**
|
||||
* An Interface representing a Remote Config value
|
||||
*/
|
||||
export interface ConfigValue {
|
||||
/**
|
||||
* Where the value was retrieved from
|
||||
*/
|
||||
source: 'remote' | 'default' | 'static';
|
||||
|
||||
/**
|
||||
* The value
|
||||
*/
|
||||
value: undefined | number | boolean | string;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing multiple Config Values
|
||||
*/
|
||||
export interface ConfigValues {
|
||||
[key: string]: ConfigValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing settable config settings.
|
||||
*/
|
||||
export interface ConfigSettingsWrite {
|
||||
isDeveloperModeEnabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing readable config settings.
|
||||
*/
|
||||
export interface ConfigSettingsRead {
|
||||
lastFetchTime: number;
|
||||
isDeveloperModeEnabled: boolean;
|
||||
lastFetchStatus: 'success' | 'failure' | 'no_fetch_yet' | 'throttled';
|
||||
}
|
||||
|
||||
/**
|
||||
* An Interface representing a Config Defaults object.
|
||||
*/
|
||||
export interface ConfigDefaults {
|
||||
[key: string]: number | string | boolean;
|
||||
}
|
||||
|
||||
export interface Module extends ReactNativeFirebaseModule {
|
||||
/**
|
||||
* Moves fetched data to the apps active config.
|
||||
* Always successfully resolves with a boolean value of whether the fetched config was moved successfully.
|
||||
*/
|
||||
activateFetched(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Fetches the remote config data from Firebase, defined in the dashboard. If duration is defined (seconds), data will be locally cached for this duration.
|
||||
*
|
||||
* @param cacheExpirationSeconds Duration in seconds to cache the data for. To force a cache use a duration of 0.
|
||||
*/
|
||||
fetch(cacheExpirationSeconds?: number): Promise<null>;
|
||||
|
||||
/**
|
||||
* Fetches the remote config data from Firebase, defined in the dashboard. If duration is defined (seconds), data will be locally cached for this duration.
|
||||
*
|
||||
* Once fetching is completely this method immediately calls activateFetched on native and returns a boolean value of activation status.
|
||||
*
|
||||
* @param cacheExpirationSeconds Duration in seconds to cache the data for. To force a cache use a duration of 0.
|
||||
*/
|
||||
fetchAndActivate(cacheExpirationSeconds?: number): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Retrieve the configuration settings and status for Remote Config.
|
||||
*/
|
||||
getConfigSettings(): Promise<ConfigSettingsRead>;
|
||||
|
||||
/**
|
||||
* Returns all keys matching the prefix as an array. If no prefix is defined all keys are returned.
|
||||
*
|
||||
* @param prefix
|
||||
*/
|
||||
getKeysByPrefix(prefix?: string): Promise<string[]>;
|
||||
|
||||
/**
|
||||
* Returns all config values for the keys matching the prefix provided. In no prefix is provided all values are returned.
|
||||
*
|
||||
* @param prefix
|
||||
*/
|
||||
getValuesByKeysPrefix(prefix?: string): Promise<ConfigValues>;
|
||||
|
||||
/**
|
||||
* Gets a ConfigValue by key.
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
getValue(key: string): Promise<ConfigValue>;
|
||||
|
||||
/**
|
||||
* Set the Remote Config settings, specifically the `isDeveloperModeEnabled` flag.
|
||||
*/
|
||||
setConfigSettings(configSettings: ConfigSettingsWrite): Promise<ConfigSettingsRead>;
|
||||
|
||||
/**
|
||||
* Sets default values for the app to use when accessing values.
|
||||
* Any data fetched and activated will override any default values. Any values in the defaults but not on Firebase will be untouched.
|
||||
*
|
||||
*/
|
||||
setDefaults(defaults: ConfigDefaults): Promise<null>;
|
||||
|
||||
/**
|
||||
* Sets the default values from a resource file.
|
||||
* On iOS this is a plist file and on Android this is an XML defaultsMap file.
|
||||
* TODO(ehesp): insert link to guide here somehow?
|
||||
*
|
||||
* @param resourceName The plist/xml file name with no extension.
|
||||
*/
|
||||
setDefaultsFromResource(resourceName: string): Promise<null>;
|
||||
}
|
||||
|
||||
declare module '@react-native-firebase/config' {
|
||||
|
||||
@@ -56,7 +56,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.crashlytics.sdk.android:crashlytics:${ReactNative.ext.getVersion("fabric", "crashlytics")}"
|
||||
implementation "com.crashlytics.sdk.android:crashlytics-ndk:${ReactNative.ext.getVersion("fabric", "crashlyticsNdk")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/crashlytics'
|
||||
rootProject.name = '@react-native-firebase_crashlytics'
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-inappmessaging-display:${ReactNative.ext.getVersion("firebase", "fiam")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/fiam'
|
||||
rootProject.name = '@react-native-firebase_fiam'
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-firestore:${ReactNative.ext.getVersion("firebase", "firestore")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/firestore'
|
||||
rootProject.name = '@react-native-firebase_firestore'
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-functions:${ReactNative.ext.getVersion("firebase", "functions")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/functions'
|
||||
rootProject.name = '@react-native-firebase_functions'
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-iid:${ReactNative.ext.getVersion("firebase", "iid")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/iid'
|
||||
rootProject.name = '@react-native-firebase_iid'
|
||||
|
||||
@@ -57,7 +57,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-ml-common:${ReactNative.ext.getVersion("firebase", "mlkitCommon")}"
|
||||
implementation "com.google.firebase:firebase-ml-vision:${ReactNative.ext.getVersion("firebase", "mlkitVision")}"
|
||||
implementation "com.google.firebase:firebase-ml-natural-language:${ReactNative.ext.getVersion("firebase", "mlkitNaturalLanguage")}"
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/mlkit'
|
||||
rootProject.name = '@react-native-firebase_mlkit'
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-perf:${ReactNative.ext.getVersion("firebase", "perf")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/perf'
|
||||
rootProject.name = '@react-native-firebase_perf'
|
||||
|
||||
@@ -51,7 +51,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/utils'
|
||||
rootProject.name = '@react-native-firebase_utils'
|
||||
|
||||
@@ -55,7 +55,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':@react-native-firebase/app')
|
||||
api project(':@react-native-firebase_app')
|
||||
implementation "com.google.firebase:firebase-_template_:${ReactNative.ext.getVersion("firebase", "_template_")}"
|
||||
implementation "com.google.android.gms:play-services-base:${ReactNative.ext.getVersion("googlePlayServices", "base")}"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
rootProject.name = '@react-native-firebase/_template_'
|
||||
rootProject.name = '@react-native-firebase__template_'
|
||||
|
||||
@@ -74,6 +74,12 @@ android {
|
||||
matchingFallbacks = ['debug']
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility 1.8
|
||||
targetCompatibility 1.8
|
||||
}
|
||||
|
||||
// applicationVariants are e.g. debug, release
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
@@ -109,7 +115,7 @@ dependencies {
|
||||
* ---------------------------- */
|
||||
|
||||
firebasePackages.each { firebasePackage ->
|
||||
implementation project(path: ":@react-native-firebase/${firebasePackage}")
|
||||
implementation project(path: ":@react-native-firebase_${firebasePackage}")
|
||||
}
|
||||
|
||||
/* ------------------------
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<defaultsMap>
|
||||
<entry>
|
||||
<key>company</key>
|
||||
<value>invertase</value>
|
||||
</entry>
|
||||
</defaultsMap>
|
||||
@@ -9,7 +9,7 @@
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
org.gradle.daemon=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.parallel=false
|
||||
org.gradle.configureondemand=true
|
||||
org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
rootProject.name = '@react-native-firebase/tests'
|
||||
rootProject.name = '@react-native-firebase_tests'
|
||||
|
||||
def firebasePackages = [
|
||||
'app',
|
||||
@@ -14,8 +14,8 @@ def firebasePackages = [
|
||||
]
|
||||
|
||||
firebasePackages.each { firebasePackage ->
|
||||
include ":@react-native-firebase/${firebasePackage}"
|
||||
project(":@react-native-firebase/${firebasePackage}").projectDir = new File(rootProject.projectDir, "./../../packages/${firebasePackage}/android")
|
||||
include ":@react-native-firebase_${firebasePackage}"
|
||||
project(":@react-native-firebase_${firebasePackage}").projectDir = new File(rootProject.projectDir, "./../../packages/${firebasePackage}/android")
|
||||
}
|
||||
|
||||
include ':jet'
|
||||
|
||||
@@ -38,6 +38,12 @@ function requirePackageTests(packageName) {
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(global, 'A2A', {
|
||||
get() {
|
||||
return require('a2a');
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(global, 'firebase', {
|
||||
get() {
|
||||
return jet.module;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
--timeout 260000
|
||||
--reporter spec
|
||||
--slow 1000
|
||||
--retries 3
|
||||
--retries 1
|
||||
--bail
|
||||
--exit
|
||||
--require jet/platform/node
|
||||
|
||||
@@ -21,6 +21,9 @@ PODS:
|
||||
- Firebase/Performance (5.17.0):
|
||||
- Firebase/Core
|
||||
- FirebasePerformance (= 2.2.3)
|
||||
- Firebase/RemoteConfig (5.17.0):
|
||||
- Firebase/Core
|
||||
- FirebaseRemoteConfig (= 3.1.0)
|
||||
- FirebaseABTesting (2.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- Protobuf (~> 3.5)
|
||||
@@ -170,6 +173,11 @@ PODS:
|
||||
- Firebase/Auth (~> 5.17.0)
|
||||
- Firebase/Core (~> 5.17.0)
|
||||
- React
|
||||
- RNFBConfig (6.0.0-alpha.5):
|
||||
- Firebase/Core (~> 5.17.0)
|
||||
- Firebase/RemoteConfig (~> 5.17.0)
|
||||
- React
|
||||
- RNFBApp
|
||||
- RNFBCrashlytics (6.0.0-alpha.5):
|
||||
- Crashlytics (~> 3.12.0)
|
||||
- Fabric (~> 1.9.0)
|
||||
@@ -218,6 +226,7 @@ DEPENDENCIES:
|
||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||
- "RNFBAnalytics (from `../node_modules/@react-native-firebase/analytics/ios`)"
|
||||
- "RNFBApp (from `../node_modules/@react-native-firebase/app/ios`)"
|
||||
- "RNFBConfig (from `../node_modules/@react-native-firebase/config/ios`)"
|
||||
- "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics/ios`)"
|
||||
- "RNFBFiam (from `../node_modules/@react-native-firebase/fiam/ios`)"
|
||||
- "RNFBFirestore (from `../node_modules/@react-native-firebase/firestore/ios`)"
|
||||
@@ -266,6 +275,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/@react-native-firebase/analytics/ios"
|
||||
RNFBApp:
|
||||
:path: "../node_modules/@react-native-firebase/app/ios"
|
||||
RNFBConfig:
|
||||
:path: "../node_modules/@react-native-firebase/config/ios"
|
||||
RNFBCrashlytics:
|
||||
:path: "../node_modules/@react-native-firebase/crashlytics/ios"
|
||||
RNFBFiam:
|
||||
@@ -312,6 +323,7 @@ SPEC CHECKSUMS:
|
||||
React: 1d605e098d69bdf08960787f3446f0a9dc2e2ccf
|
||||
RNFBAnalytics: 61b9d722deb136454425850860df910250a1874d
|
||||
RNFBApp: ea2649b5993bec4ef4ff5ed4cb29454328e78b74
|
||||
RNFBConfig: 7804a2113cb720f6819c3b289a1bee8342b82aad
|
||||
RNFBCrashlytics: b7ec197ade3caaa6060525b506fd2ff65b529a4c
|
||||
RNFBFiam: 7ea892c593296cfb74bced95d96717c991233c69
|
||||
RNFBFirestore: 5cc04b0781abd2a0c339738dcc56fc76a5930ac0
|
||||
|
||||
8
tests/ios/remote_config_resource_test.plist
Normal file
8
tests/ios/remote_config_resource_test.plist
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>company</key>
|
||||
<string>invertase</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -11,6 +11,7 @@
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
271CB185206AFCD300EBADF4 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 271CB184206AFCD300EBADF4 /* GoogleService-Info.plist */; };
|
||||
27CE6A36224923D200222E16 /* remote_config_resource_test.plist in Resources */ = {isa = PBXBuildFile; fileRef = 27CE6A35224923D200222E16 /* remote_config_resource_test.plist */; };
|
||||
3323F06104C7189BEC46D8B5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3323FFA47718EA67C36AD776 /* Images.xcassets */; };
|
||||
E31DA68013C367A4C7A4C7C7 /* Pods_testing.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0468979958B59C09A7C97954 /* Pods_testing.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -40,6 +41,7 @@
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = testing/main.m; sourceTree = "<group>"; };
|
||||
27034D93212869A1004B697E /* testing.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = testing.entitlements; path = testing/testing.entitlements; sourceTree = "<group>"; };
|
||||
271CB184206AFCD300EBADF4 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
27CE6A35224923D200222E16 /* remote_config_resource_test.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = remote_config_resource_test.plist; sourceTree = "<group>"; };
|
||||
30F8459A53F04DD0B22777D1 /* testing.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; path = testing.xcodeproj; sourceTree = "<group>"; };
|
||||
3323FFA47718EA67C36AD776 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = testing/Images.xcassets; sourceTree = "<group>"; };
|
||||
4C4B32475FBBBAC16708CB5B /* Pods-testing.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testing.debug.xcconfig"; path = "Pods/Target Support Files/Pods-testing/Pods-testing.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
@@ -85,6 +87,7 @@
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
27CE6A35224923D200222E16 /* remote_config_resource_test.plist */,
|
||||
);
|
||||
name = testing;
|
||||
sourceTree = "<group>";
|
||||
@@ -227,6 +230,7 @@
|
||||
files = (
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
271CB185206AFCD300EBADF4 /* GoogleService-Info.plist in Resources */,
|
||||
27CE6A36224923D200222E16 /* remote_config_resource_test.plist in Resources */,
|
||||
3323F06104C7189BEC46D8B5 /* Images.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"sinon": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"a2a": "^0.2.0",
|
||||
"@react-native-firebase/private-tests-helpers": "^0.0.8",
|
||||
"babel-plugin-istanbul": "^5.1.1",
|
||||
"nyc": "^13.1.0",
|
||||
|
||||
@@ -1,28 +1,17 @@
|
||||
import firebase from 'react-native-firebase';
|
||||
import '@react-native-firebase/iid';
|
||||
import analytics, { Analytics } from '@react-native-firebase/analytics';
|
||||
import functions, {
|
||||
firebase as boopy,
|
||||
Functions,
|
||||
HttpsErrorCode,
|
||||
} from '@react-native-firebase/functions';
|
||||
import '@react-native-firebase/config';
|
||||
import '@react-native-firebase/functions';
|
||||
import { firebase } from '@react-native-firebase/analytics';
|
||||
|
||||
boopy.apps[0].options.projectId;
|
||||
analytics.SDK_VERSION;
|
||||
functions.SDK_VERSION;
|
||||
const httpsCallable = firebase.functions(firebase.app()).httpsCallable('foo');
|
||||
functions;
|
||||
async () => {
|
||||
await firebase.config().activateFetched();
|
||||
await firebase.config().fetch(0);
|
||||
await firebase.config().fetch();
|
||||
|
||||
firebase.iid().get();
|
||||
firebase.analytics().resetAnalyticsData();
|
||||
const settings = await firebase.config().getConfigSettings();
|
||||
console.log(settings.isDeveloperModeEnabled);
|
||||
console.log(settings.lastFetchStatus);
|
||||
console.log(settings.lastFetchTime);
|
||||
|
||||
httpsCallable({ foo: 1 })
|
||||
.then(result => {
|
||||
result.data;
|
||||
})
|
||||
.catch((error: Functions.HttpsError) => {
|
||||
const foo = {} as Analytics.Module;
|
||||
error.details;
|
||||
foo.logEvent('shoopy', {});
|
||||
HttpsErrorCode.NOT_FOUND;
|
||||
});
|
||||
await firebase.config().setConfigSettings({ isDeveloperModeEnabled: false });
|
||||
await firebase.config().setDefaults({ foo: null });
|
||||
};
|
||||
|
||||
@@ -1488,6 +1488,11 @@ JSONStream@^1.0.4, JSONStream@^1.3.4:
|
||||
jsonparse "^1.2.0"
|
||||
through ">=2.2.7 <3"
|
||||
|
||||
a2a@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/a2a/-/a2a-0.2.0.tgz#32bcbc13457636a9cd37f0c3674778120e3a847c"
|
||||
integrity sha512-zacbQ73PcKwlC4dFqaD5GDvluv2I7owHYELi6PCDERcZVFm0LNuhWGm1CKwtxcxEF7SmQXVF342wBKO8xAayMg==
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
|
||||
Reference in New Issue
Block a user