diff --git a/android/src/main/java/com/launchdarkly/reactnative/LaunchdarklyReactNativeClientModule.java b/android/src/main/java/com/launchdarkly/reactnative/LaunchdarklyReactNativeClientModule.java
index 610cd52..9bf022c 100644
--- a/android/src/main/java/com/launchdarkly/reactnative/LaunchdarklyReactNativeClientModule.java
+++ b/android/src/main/java/com/launchdarkly/reactnative/LaunchdarklyReactNativeClientModule.java
@@ -50,23 +50,8 @@
import timber.log.Timber;
-/**
- * Module bound with React Native to be called from JavaScript
- */
public class LaunchdarklyReactNativeClientModule extends ReactContextBaseJavaModule {
- /**
- * An enum of all the supported configuration entries for LDClient configuration.
- *
- *
- * Each enum value has a lookup key, entry type, and internal setter associated with it. The
- * lookup key is used to get the configuration value from a ReadableMap (JsonObject passed over
- * the react native bridge). The entry type specifies the base type looked up from the
- * ReadableMap as well as any additional conversion needed before setting the internal LDConfig
- * option, see @see ConfigEntryType for more. The internal setter is a String name of the setter
- * method used to pass the parsed configuration value into a LDConfig builder used for LDClient
- * setup.
- */
enum ConfigMapping {
CONFIG_MOBILE_KEY("mobileKey", ConfigEntryType.String, "setMobileKey"),
CONFIG_BASE_URI("pollUri", ConfigEntryType.Uri, "setPollUri"),
@@ -87,7 +72,8 @@ enum ConfigMapping {
CONFIG_WRAPPER_VERSION("wrapperVersion", ConfigEntryType.String, "setWrapperVersion"),
CONFIG_MAX_CACHED_USERS("maxCachedUsers", ConfigEntryType.Integer, "setMaxCachedUsers"),
CONFIG_DIAGNOSTIC_OPT_OUT("diagnosticOptOut", ConfigEntryType.Boolean, "setDiagnosticOptOut"),
- CONFIG_DIAGNOSTIC_RECORDING_INTERVAL("diagnosticRecordingIntervalMillis", ConfigEntryType.Integer, "setDiagnosticRecordingIntervalMillis");
+ CONFIG_DIAGNOSTIC_RECORDING_INTERVAL("diagnosticRecordingIntervalMillis", ConfigEntryType.Integer, "setDiagnosticRecordingIntervalMillis"),
+ CONFIG_SECONDARY_MOBILE_KEYS("secondaryMobileKeys", ConfigEntryType.Map, "setSecondaryMobileKeys");
final String key;
final ConfigEntryType type;
@@ -112,17 +98,6 @@ void loadFromMap(ReadableMap map, LDConfig.Builder builder) {
}
}
- /**
- * An enum of all the supported configuration entries for LDUser configuration.
- *
- *
- * Each enum value has a lookup key, entry type, and internal setter associated with it. The
- * lookup key is used to get the configuration value from a ReadableMap (JsonObject passed over
- * the react native bridge). The entry type specifies the base type looked up from the
- * ReadableMap as well as any additional conversion needed before setting the internal LDUser
- * option, @see ConfigEntryType for more. The internal setter is a String name of the setter
- * method used to pass the parsed configuration value into a LDUser builder.
- */
enum UserConfigMapping {
USER_ANONYMOUS("anonymous", ConfigEntryType.Boolean, "anonymous", null),
USER_IP("ip", ConfigEntryType.String, "ip", "privateIp"),
@@ -163,9 +138,6 @@ void loadFromMap(ReadableMap map, LDUser.Builder builder, Set privateAtt
}
}
- // The LDClient instance
- private LDClient ldClient;
- // Current feature flag listeners
private Map listeners = new HashMap<>();
private Map connectionModeListeners = new HashMap<>();
private Map allFlagsListeners = new HashMap<>();
@@ -188,18 +160,15 @@ public String getName() {
return "LaunchdarklyReactNativeClient";
}
- // Constants used in promise rejection
private static final String ERROR_INIT = "E_INITIALIZE";
private static final String ERROR_IDENTIFY = "E_IDENTIFY";
private static final String ERROR_CLOSE = "E_CLOSE";
private static final String ERROR_UNKNOWN = "E_UNKNOWN";
- // Prefix for events sent over the React Native event bridge
private static final String FLAG_PREFIX = "LaunchDarkly-Flag-";
private static final String ALL_FLAGS_PREFIX = "LaunchDarkly-All-Flags-";
private static final String CONNECTION_MODE_PREFIX = "LaunchDarkly-Connection-Mode-";
-
/**
* Called automatically by the React Native bridging layer to associate constants with the
* object used to call into native modules.
@@ -215,38 +184,27 @@ public Map getConstants() {
return constants;
}
- /**
- * React Method called from JavaScript to initialize the LDClient using the supplied
- * configuration.
- *
- * @param config LDConfig configuration, @see configBuild
- * @param user LDUser configuration, @see userBuild
- * @param promise Either rejected if an error was encountered, otherwise resolved with null
- * once client is initialized.
- */
@ReactMethod
public void configure(ReadableMap config, ReadableMap user, final Promise promise) {
internalConfigure(config, user, null, promise);
}
- /**
- * React Method called from JavaScript to initialize the LDClient using the supplied
- * configuration with a timeout.
- *
- * @param config LDConfig configuration, @see configBuild
- * @param user LDUser configuration, @see userBuild
- * @param timeout Integer that blocks until the latest feature flags have been retrieved from LaunchDarkly
- * @param promise Either rejected if an error was encountered, otherwise resolved with null
- * once client is initialized.
- */
@ReactMethod
public void configureWithTimeout(ReadableMap config, ReadableMap user, Integer timeout, final Promise promise) {
internalConfigure(config, user, timeout, promise);
}
private void internalConfigure(ReadableMap config, ReadableMap user, final Integer timeout, final Promise promise) {
- if (ldClient != null) {
- promise.reject(ERROR_INIT, "Client was already initialized");
+ try {
+ if (LDClient.get() != null) {
+ promise.reject(ERROR_INIT, "Client was already initialized");
+ return;
+ }
+ } catch (LaunchDarklyException e) {
+ //This exception indicates that the SDK has not been initialized yet
+ } catch (Exception e) {
+ Timber.w(e);
+ promise.reject(ERROR_INIT, e);
return;
}
@@ -264,7 +222,7 @@ private void internalConfigure(ReadableMap config, ReadableMap user, final Integ
}
if (config.hasKey("allUserAttributesPrivate")
- && config.getType("allUserAttributesPrivate").equals(ConfigEntryType.Boolean.getReadableType())
+ && config.getType("allUserAttributesPrivate").equals(ConfigEntryType.Boolean.getReadableType())
&& config.getBoolean("allUserAttributesPrivate")) {
ldConfigBuilder.allAttributesPrivate();
}
@@ -275,23 +233,12 @@ private void internalConfigure(ReadableMap config, ReadableMap user, final Integ
Thread background = new Thread(new Runnable() {
@Override
public void run() {
- try {
- if (timeout != null) {
- ldClient = LDClient.init(application, ldConfigBuilder.build(), userBuilder.build(), timeout).get();
- } else {
- ldClient = LDClient.init(application, ldConfigBuilder.build(), userBuilder.build()).get();
- }
- promise.resolve(null);
- } catch (InterruptedException e) {
- Timber.w(e);
- promise.reject(ERROR_INIT, e);
- } catch (ExecutionException e) {
- Timber.w(e);
- promise.reject(ERROR_INIT, e);
- } catch (LaunchDarklyException e) {
- Timber.w(e);
- promise.reject(ERROR_INIT, e);
+ if (timeout != null) {
+ LDClient.init(application, ldConfigBuilder.build(), userBuilder.build(), timeout);
+ } else {
+ LDClient.init(application, ldConfigBuilder.build(), userBuilder.build());
}
+ promise.resolve(null);
}
});
@@ -302,15 +249,6 @@ public void run() {
}
}
- /**
- * Create a LDConfig.Builder using configuration values from the options ReadableMap.
- *
- *
- * This will look for all configuration values specified in {@link ConfigMapping}.
- *
- * @param options A ReadableMap of configuration options
- * @return A LDConfig.Builder configured with options
- */
private LDConfig.Builder configBuild(ReadableMap options) {
LDConfig.Builder builder = new LDConfig.Builder();
@@ -321,15 +259,6 @@ private LDConfig.Builder configBuild(ReadableMap options) {
return builder;
}
- /**
- * Create a LDUser.Builder using configuration values from the options ReadableMap.
- *
- *
- * This will look for all configuration values specified in {@link UserConfigMapping}.
- *
- * @param options A ReadableMap of configuration options
- * @return A LDUser.Builder configured with options
- */
private LDUser.Builder userBuild(ReadableMap options) {
if (!options.hasKey("key")) {
return null;
@@ -433,180 +362,101 @@ private LDUser.Builder userBuild(ReadableMap options) {
}
@ReactMethod
- public void boolVariation(String flagKey, Promise promise) {
- boolVariationDefaultValue(flagKey, null, promise);
+ public void boolVariation(String flagKey, String environment, Promise promise) {
+ boolVariationDefaultValue(flagKey, null, environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void boolVariationDefaultValue(String flagKey, Boolean defaultValue, Promise promise) {
+ public void boolVariationDefaultValue(String flagKey, Boolean defaultValue, String environment, Promise promise) {
try {
- promise.resolve(ldClient.boolVariation(flagKey, defaultValue));
+ promise.resolve(LDClient.getForMobileKey(environment).boolVariation(flagKey, defaultValue));
} catch (Exception e) {
promise.resolve(defaultValue);
}
}
@ReactMethod
- public void intVariation(String flagKey, Promise promise) {
- intVariationDefaultValue(flagKey, null, promise);
+ public void intVariation(String flagKey, String environment, Promise promise) {
+ intVariationDefaultValue(flagKey, null, environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void intVariationDefaultValue(String flagKey, Integer defaultValue, Promise promise) {
+ public void intVariationDefaultValue(String flagKey, Integer defaultValue, String environment, Promise promise) {
try {
- promise.resolve(ldClient.intVariation(flagKey, defaultValue));
+ promise.resolve(LDClient.getForMobileKey(environment).intVariation(flagKey, defaultValue));
} catch (Exception e) {
promise.resolve(defaultValue);
}
}
@ReactMethod
- public void floatVariation(String flagKey, Promise promise) {
- floatVariationDefaultValue(flagKey, null, promise);
+ public void floatVariation(String flagKey, String environment, Promise promise) {
+ floatVariationDefaultValue(flagKey, null, environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void floatVariationDefaultValue(String flagKey, Double defaultValue, Promise promise) {
+ public void floatVariationDefaultValue(String flagKey, Float defaultValue, String environment, Promise promise) {
try {
- promise.resolve(ldClient.doubleVariation(flagKey, defaultValue));
+ promise.resolve(LDClient.getForMobileKey(environment).doubleVariation(flagKey, defaultValue.doubleValue()));
} catch (Exception e) {
promise.resolve(defaultValue);
}
}
@ReactMethod
- public void stringVariation(String flagKey, Promise promise) {
- stringVariationDefaultValue(flagKey, null, promise);
+ public void stringVariation(String flagKey, String environment, Promise promise) {
+ stringVariationDefaultValue(flagKey, null, environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void stringVariationDefaultValue(String flagKey, String defaultValue, Promise promise) {
+ public void stringVariationDefaultValue(String flagKey, String defaultValue, String environment, Promise promise) {
try {
- promise.resolve(ldClient.stringVariation(flagKey, defaultValue));
+ promise.resolve(LDClient.getForMobileKey(environment).stringVariation(flagKey, defaultValue));
} catch (Exception e) {
promise.resolve(defaultValue);
}
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns null
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void jsonVariationNone(String flagKey, Promise promise) {
- jsonVariationBase(flagKey, null, promise);
+ public void jsonVariationNone(String flagKey, String environment, Promise promise) {
+ jsonVariationBase(flagKey, null, environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void jsonVariationNumber(String flagKey, Double defaultValue, Promise promise) {
- jsonVariationBase(flagKey, new JsonPrimitive(defaultValue), promise);
+ public void jsonVariationNumber(String flagKey, Double defaultValue, String environment, Promise promise) {
+ jsonVariationBase(flagKey, new JsonPrimitive(defaultValue), environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void jsonVariationBool(String flagKey, Boolean defaultValue, Promise promise) {
- jsonVariationBase(flagKey, new JsonPrimitive(defaultValue), promise);
+ public void jsonVariationBool(String flagKey, Boolean defaultValue, String environment, Promise promise) {
+ jsonVariationBase(flagKey, new JsonPrimitive(defaultValue), environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void jsonVariationString(String flagKey, String defaultValue, Promise promise) {
- jsonVariationBase(flagKey, new JsonPrimitive(defaultValue), promise);
+ public void jsonVariationString(String flagKey, String defaultValue, String environment, Promise promise) {
+ jsonVariationBase(flagKey, new JsonPrimitive(defaultValue), environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void jsonVariationArray(String flagKey, ReadableArray defaultValue, Promise promise) {
- jsonVariationBase(flagKey, toJsonArray(defaultValue), promise);
+ public void jsonVariationArray(String flagKey, ReadableArray defaultValue, String environment, Promise promise) {
+ jsonVariationBase(flagKey, toJsonArray(defaultValue), environment, promise);
}
- /**
- * Looks up the current value for a flag, in the case of any issues, returns the given default
- * value.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if current value could not be acquired.
- * @param promise Used to return the result to React Native
- */
@ReactMethod
- public void jsonVariationObject(String flagKey, ReadableMap defaultValue, Promise promise) {
- jsonVariationBase(flagKey, toJsonObject(defaultValue), promise);
+ public void jsonVariationObject(String flagKey, ReadableMap defaultValue, String environment, Promise promise) {
+ jsonVariationBase(flagKey, toJsonObject(defaultValue), environment, promise);
}
@ReactMethod
- public void boolVariationDetail(String flagKey, Promise promise) {
- boolVariationDetailDefaultValue(flagKey, null, promise);
+ public void boolVariationDetail(String flagKey, String environment, Promise promise) {
+ boolVariationDetailDefaultValue(flagKey, null, environment, promise);
}
@ReactMethod
- public void boolVariationDetailDefaultValue(String flagKey, Boolean defaultValue, Promise promise) {
+ public void boolVariationDetailDefaultValue(String flagKey, Boolean defaultValue, String environment, Promise promise) {
EvaluationDetail detailResult;
try {
- detailResult = ldClient.boolVariationDetail(flagKey, defaultValue);
+ detailResult = LDClient.getForMobileKey(environment).boolVariationDetail(flagKey, defaultValue);
} catch (Exception e) {
Timber.w(e);
detailResult = new EvaluationDetail(EvaluationReason.error(EvaluationReason.ErrorKind.EXCEPTION), null, defaultValue);
@@ -617,15 +467,15 @@ public void boolVariationDetailDefaultValue(String flagKey, Boolean defaultValue
}
@ReactMethod
- public void intVariationDetail(String flagKey, Promise promise) {
- intVariationDetailDefaultValue(flagKey, null, promise);
+ public void intVariationDetail(String flagKey, String environment, Promise promise) {
+ intVariationDetailDefaultValue(flagKey, null, environment, promise);
}
@ReactMethod
- public void intVariationDetailDefaultValue(String flagKey, Integer defaultValue, Promise promise) {
+ public void intVariationDetailDefaultValue(String flagKey, Integer defaultValue, String environment, Promise promise) {
EvaluationDetail detailResult;
try {
- detailResult = ldClient.intVariationDetail(flagKey, defaultValue);
+ detailResult = LDClient.getForMobileKey(environment).intVariationDetail(flagKey, defaultValue);
} catch (Exception e) {
Timber.w(e);
detailResult = new EvaluationDetail(EvaluationReason.error(EvaluationReason.ErrorKind.EXCEPTION), null, defaultValue);
@@ -636,18 +486,19 @@ public void intVariationDetailDefaultValue(String flagKey, Integer defaultValue,
}
@ReactMethod
- public void floatVariationDetail(String flagKey, Promise promise) {
- floatVariationDetailDefaultValue(flagKey, null, promise);
+ public void floatVariationDetail(String flagKey, String environment, Promise promise) {
+ floatVariationDetailDefaultValue(flagKey, null, environment, promise);
}
@ReactMethod
- public void floatVariationDetailDefaultValue(String flagKey, Double defaultValue, Promise promise) {
+ public void floatVariationDetailDefaultValue(String flagKey, Float defaultValue, String environment, Promise promise) {
EvaluationDetail detailResult;
+ Double doubleValue = defaultValue.doubleValue();
try {
- detailResult = ldClient.doubleVariationDetail(flagKey, defaultValue);
+ detailResult = LDClient.getForMobileKey(environment).doubleVariationDetail(flagKey, doubleValue);
} catch (Exception e) {
Timber.w(e);
- detailResult = new EvaluationDetail(EvaluationReason.error(EvaluationReason.ErrorKind.EXCEPTION), null, defaultValue);
+ detailResult = new EvaluationDetail(EvaluationReason.error(EvaluationReason.ErrorKind.EXCEPTION), null, doubleValue);
}
JsonObject jsonObject = gson.toJsonTree(detailResult).getAsJsonObject();
WritableMap detailMap = fromJsonObject(jsonObject);
@@ -655,15 +506,15 @@ public void floatVariationDetailDefaultValue(String flagKey, Double defaultValue
}
@ReactMethod
- public void stringVariationDetail(String flagKey, Promise promise) {
- stringVariationDetailDefaultValue(flagKey, null, promise);
+ public void stringVariationDetail(String flagKey, String environment, Promise promise) {
+ stringVariationDetailDefaultValue(flagKey, null, environment, promise);
}
@ReactMethod
- public void stringVariationDetailDefaultValue(String flagKey, String defaultValue, Promise promise) {
+ public void stringVariationDetailDefaultValue(String flagKey, String defaultValue, String environment, Promise promise) {
EvaluationDetail detailResult;
try {
- detailResult = ldClient.stringVariationDetail(flagKey, defaultValue);
+ detailResult = LDClient.getForMobileKey(environment).stringVariationDetail(flagKey, defaultValue);
} catch (Exception e) {
Timber.w(e);
detailResult = new EvaluationDetail(EvaluationReason.error(EvaluationReason.ErrorKind.EXCEPTION), null, defaultValue);
@@ -674,55 +525,49 @@ public void stringVariationDetailDefaultValue(String flagKey, String defaultValu
}
@ReactMethod
- public void jsonVariationDetailNone(String flagKey, Promise promise) {
- jsonVariationDetailBase(flagKey, null, promise);
+ public void jsonVariationDetailNone(String flagKey, String environment, Promise promise) {
+ jsonVariationDetailBase(flagKey, null, environment, promise);
}
@ReactMethod
- public void jsonVariationDetailNumber(String flagKey, Double defaultValue, Promise promise) {
- jsonVariationDetailBase(flagKey, new JsonPrimitive(defaultValue), promise);
+ public void jsonVariationDetailNumber(String flagKey, Double defaultValue, String environment, Promise promise) {
+ jsonVariationDetailBase(flagKey, new JsonPrimitive(defaultValue), environment, promise);
}
@ReactMethod
- public void jsonVariationDetailBool(String flagKey, Boolean defaultValue, Promise promise) {
- jsonVariationDetailBase(flagKey, new JsonPrimitive(defaultValue), promise);
+ public void jsonVariationDetailBool(String flagKey, Boolean defaultValue, String environment, Promise promise) {
+ jsonVariationDetailBase(flagKey, new JsonPrimitive(defaultValue), environment, promise);
}
@ReactMethod
- public void jsonVariationDetailString(String flagKey, String defaultValue, Promise promise) {
- jsonVariationDetailBase(flagKey, new JsonPrimitive(defaultValue), promise);
+ public void jsonVariationDetailString(String flagKey, String defaultValue, String environment, Promise promise) {
+ jsonVariationDetailBase(flagKey, new JsonPrimitive(defaultValue), environment, promise);
}
@ReactMethod
- public void jsonVariationDetailArray(String flagKey, ReadableArray defaultValue, Promise promise) {
- jsonVariationDetailBase(flagKey, toJsonArray(defaultValue), promise);
+ public void jsonVariationDetailArray(String flagKey, ReadableArray defaultValue, String environment, Promise promise) {
+ jsonVariationDetailBase(flagKey, toJsonArray(defaultValue), environment, promise);
}
@ReactMethod
- public void jsonVariationDetailObject(String flagKey, ReadableMap defaultValue, Promise promise) {
- jsonVariationDetailBase(flagKey, toJsonObject(defaultValue), promise);
+ public void jsonVariationDetailObject(String flagKey, ReadableMap defaultValue, String environment, Promise promise) {
+ jsonVariationDetailBase(flagKey, toJsonObject(defaultValue), environment, promise);
}
- /**
- * Helper for jsonVariation methods.
- *
- * @param flagKey The lookup key of the flag.
- * @param defaultValue A default value to return if the current value could not be acquired.
- * @param promise Used to return the result to React Native.
- */
- private void jsonVariationBase(String flagKey, JsonElement defaultValue, Promise promise) {
- try {
- JsonElement jsonElement = ldClient.jsonVariation(flagKey, defaultValue);
+ private void jsonVariationBase(String flagKey, JsonElement defaultValue, String environment, Promise promise) {
+ JsonElement jsonElement;
+ try {
+ jsonElement = LDClient.getForMobileKey(environment).jsonVariation(flagKey, defaultValue);
resolveJsonElement(promise, jsonElement);
} catch (Exception e) {
resolveJsonElement(promise, defaultValue);
}
}
- private void jsonVariationDetailBase(String flagKey, JsonElement defaultValue, Promise promise) {
+ private void jsonVariationDetailBase(String flagKey, JsonElement defaultValue, String environment, Promise promise) {
EvaluationDetail jsonElementDetail;
try {
- jsonElementDetail = ldClient.jsonVariationDetail(flagKey, defaultValue);
+ jsonElementDetail = LDClient.getForMobileKey(environment).jsonVariationDetail(flagKey, defaultValue);
} catch (Exception e) {
Timber.w(e);
jsonElementDetail = new EvaluationDetail(EvaluationReason.error(EvaluationReason.ErrorKind.EXCEPTION), null, defaultValue);
@@ -730,14 +575,6 @@ private void jsonVariationDetailBase(String flagKey, JsonElement defaultValue, P
resolveJsonElementDetail(promise, jsonElementDetail);
}
-
- /**
- * Converts the jsonElement to a React Native bridge compatible type and resolves the promise
- * with it's value.
- *
- * @param promise Promise to resolve
- * @param jsonElement Value to convert and resolve promise with.
- */
private void resolveJsonElement(Promise promise, JsonElement jsonElement) {
if (jsonElement == null || jsonElement.isJsonNull()) {
promise.resolve(null);
@@ -765,319 +602,237 @@ private void resolveJsonElementDetail(Promise promise, EvaluationDetail flags = ldClient.allFlags();
-
- // Convert map of all flags into WritableMap for React Native
- WritableMap response = new WritableNativeMap();
- for (Map.Entry entry : flags.entrySet()) {
- if (entry.getValue() == null) {
- response.putNull(entry.getKey());
- } else if (entry.getValue() instanceof String) {
- try {
- JsonElement parsedJson = new JsonParser().parse((String) entry.getValue());
- if (parsedJson.isJsonObject()) {
- response.putMap(entry.getKey(), fromJsonObject((JsonObject) parsedJson.getAsJsonObject()));
- } else if (parsedJson.isJsonArray()) {
- response.putArray(entry.getKey(), fromJsonArray((JsonArray) parsedJson.getAsJsonArray()));
- } else {
+ try {
+ Map flags = LDClient.getForMobileKey(environment).allFlags();
+
+ WritableMap response = new WritableNativeMap();
+ for (Map.Entry entry : flags.entrySet()) {
+ if (entry.getValue() == null) {
+ response.putNull(entry.getKey());
+ } else if (entry.getValue() instanceof String) {
+ try {
+ JsonElement parsedJson = new JsonParser().parse((String) entry.getValue());
+ if (parsedJson.isJsonObject()) {
+ response.putMap(entry.getKey(), fromJsonObject((JsonObject) parsedJson.getAsJsonObject()));
+ } else if (parsedJson.isJsonArray()) {
+ response.putArray(entry.getKey(), fromJsonArray((JsonArray) parsedJson.getAsJsonArray()));
+ } else {
+ response.putString(entry.getKey(),(String) entry.getValue());
+ }
+ } catch (JsonParseException e) {
response.putString(entry.getKey(),(String) entry.getValue());
}
- } catch (JsonParseException e) {
- response.putString(entry.getKey(),(String) entry.getValue());
- }
- } else if (entry.getValue() instanceof Boolean) {
- response.putBoolean(entry.getKey(), (Boolean) entry.getValue());
- } else if (entry.getValue() instanceof Double) {
- response.putDouble(entry.getKey(), (Double) entry.getValue());
- } else if (entry.getValue() instanceof Float) {
- response.putDouble(entry.getKey(), (Float) entry.getValue());
- } else if (entry.getValue() instanceof Integer) {
- response.putInt(entry.getKey(), (Integer) entry.getValue());
- } else if (entry.getValue() instanceof JsonNull) {
- response.putNull(entry.getKey());
- } else if (entry.getValue() instanceof JsonArray) {
- response.putArray(entry.getKey(), fromJsonArray((JsonArray) entry.getValue()));
- } else if (entry.getValue() instanceof JsonObject) {
- response.putMap(entry.getKey(), fromJsonObject((JsonObject) entry.getValue()));
- } else if (entry.getValue() instanceof JsonPrimitive) {
- JsonPrimitive primitive = (JsonPrimitive) entry.getValue();
- if (primitive.isString()) {
- response.putString(entry.getKey(), primitive.getAsString());
- } else if (primitive.isBoolean()) {
- response.putBoolean(entry.getKey(), primitive.getAsBoolean());
- } else if (primitive.isNumber()) {
- response.putDouble(entry.getKey(), primitive.getAsDouble());
+ } else if (entry.getValue() instanceof Boolean) {
+ response.putBoolean(entry.getKey(), (Boolean) entry.getValue());
+ } else if (entry.getValue() instanceof Double) {
+ response.putDouble(entry.getKey(), (Double) entry.getValue());
+ } else if (entry.getValue() instanceof Float) {
+ response.putDouble(entry.getKey(), (Float) entry.getValue());
+ } else if (entry.getValue() instanceof Integer) {
+ response.putInt(entry.getKey(), (Integer) entry.getValue());
+ } else if (entry.getValue() instanceof JsonNull) {
+ response.putNull(entry.getKey());
+ } else if (entry.getValue() instanceof JsonArray) {
+ response.putArray(entry.getKey(), fromJsonArray((JsonArray) entry.getValue()));
+ } else if (entry.getValue() instanceof JsonObject) {
+ response.putMap(entry.getKey(), fromJsonObject((JsonObject) entry.getValue()));
+ } else if (entry.getValue() instanceof JsonPrimitive) {
+ JsonPrimitive primitive = (JsonPrimitive) entry.getValue();
+ if (primitive.isString()) {
+ response.putString(entry.getKey(), primitive.getAsString());
+ } else if (primitive.isBoolean()) {
+ response.putBoolean(entry.getKey(), primitive.getAsBoolean());
+ } else if (primitive.isNumber()) {
+ response.putDouble(entry.getKey(), primitive.getAsDouble());
+ }
}
}
+ promise.resolve(response);
+ } catch (Exception e) {
+ Timber.w(e);
}
- promise.resolve(response);
}
- /**
- * Runs the SDK's trackData method with a number as custom data
- *
- * Separately typed methods are necessary at the React Native bridging layer requires that
- * bridged method types disambiguate the value type.
- *
- * @param eventName Name of the event to track
- * @param data The Double data to attach to the tracking event
- */
@ReactMethod
- public void trackNumber(String eventName, Double data) {
+ public void trackNumber(String eventName, Double data, String environment) {
try {
- ldClient.track(eventName, new JsonPrimitive(data));
+ LDClient.getForMobileKey(environment).track(eventName, new JsonPrimitive(data));
} catch (Exception e) {
Timber.w(e);
}
}
- /**
- * Runs the SDK's trackData method with a Boolean as custom data
- *
- * Separately typed methods are necessary at the React Native bridging layer requires that
- * bridged method types disambiguate the value type.
- *
- * @param eventName Name of the event to track
- * @param data The Boolean data to attach to the tracking event
- */
@ReactMethod
- public void trackBool(String eventName, Boolean data) {
+ public void trackBool(String eventName, Boolean data, String environment) {
try {
- ldClient.track(eventName, new JsonPrimitive(data));
+ LDClient.getForMobileKey(environment).track(eventName, new JsonPrimitive(data));
} catch (Exception e) {
Timber.w(e);
}
}
- /**
- * Runs the SDK's trackData method with a String as custom data
- *
- * Separately typed methods are necessary at the React Native bridging layer requires that
- * bridged method types disambiguate the value type.
- *
- * @param eventName Name of the event to track
- * @param data The String data to attach to the tracking event
- */
@ReactMethod
- public void trackString(String eventName, String data) {
+ public void trackString(String eventName, String data, String environment) {
try {
- ldClient.track(eventName, new JsonPrimitive(data));
+ LDClient.getForMobileKey(environment).track(eventName, new JsonPrimitive(data));
} catch (Exception e) {
Timber.w(e);
}
}
- /**
- * Runs the SDK's trackData method with an Array as custom data
- *
- * Separately typed methods are necessary at the React Native bridging layer requires that
- * bridged method types disambiguate the value type.
- *
- * @param eventName Name of the event to track
- * @param data The Array data to attach to the tracking event
- */
@ReactMethod
- public void trackArray(String eventName, ReadableArray data) {
+ public void trackArray(String eventName, ReadableArray data, String environment) {
try {
- ldClient.track(eventName, toJsonArray(data));
+ LDClient.getForMobileKey(environment).track(eventName, toJsonArray(data));
} catch (Exception e) {
Timber.w(e);
}
}
- /**
- * Runs the SDK's trackData method with an object as custom data
- *
- * Separately typed methods are necessary at the React Native bridging layer requires that
- * bridged method types disambiguate the value type.
- *
- * @param eventName Name of the event to track
- * @param data The Map(Object) data to attach to the tracking event
- */
@ReactMethod
- public void trackObject(String eventName, ReadableMap data) {
+ public void trackObject(String eventName, ReadableMap data, String environment) {
try {
- ldClient.track(eventName, toJsonObject(data));
+ LDClient.getForMobileKey(environment).track(eventName, toJsonObject(data));
} catch (Exception e) {
Timber.w(e);
}
}
- /**
- * Track an event with a custom name.
- *
- * @param eventName Name of the event
- */
@ReactMethod
- public void track(String eventName) {
+ public void track(String eventName, String environment) {
try {
- ldClient.track(eventName);
+ LDClient.getForMobileKey(environment).track(eventName);
} catch (Exception e) {
Timber.w(e);
}
}
@ReactMethod
- public void trackNumberMetricValue(String eventName, Double data, Double metricValue) {
+ public void trackNumberMetricValue(String eventName, Double data, Double metricValue, String environment) {
try {
- ldClient.track(eventName, new JsonPrimitive(data), metricValue);
+ LDClient.getForMobileKey(environment).track(eventName, new JsonPrimitive(data), metricValue);
} catch (Exception e) {
Timber.w(e);
}
}
@ReactMethod
- public void trackBoolMetricValue(String eventName, Boolean data, Double metricValue) {
+ public void trackBoolMetricValue(String eventName, Boolean data, Double metricValue, String environment) {
try {
- ldClient.track(eventName, new JsonPrimitive(data), metricValue);
+ LDClient.getForMobileKey(environment).track(eventName, new JsonPrimitive(data), metricValue);
} catch (Exception e) {
Timber.w(e);
}
}
@ReactMethod
- public void trackStringMetricValue(String eventName, String data, Double metricValue) {
+ public void trackStringMetricValue(String eventName, String data, Double metricValue, String environment) {
try {
- ldClient.track(eventName, new JsonPrimitive(data), metricValue);
+ LDClient.getForMobileKey(environment).track(eventName, new JsonPrimitive(data), metricValue);
} catch (Exception e) {
Timber.w(e);
}
}
@ReactMethod
- public void trackArrayMetricValue(String eventName, ReadableArray data, Double metricValue) {
+ public void trackArrayMetricValue(String eventName, ReadableArray data, Double metricValue, String environment) {
try {
- ldClient.track(eventName, toJsonArray(data), metricValue);
+ LDClient.getForMobileKey(environment).track(eventName, toJsonArray(data), metricValue);
} catch (Exception e) {
Timber.w(e);
}
}
@ReactMethod
- public void trackObjectMetricValue(String eventName, ReadableMap data, Double metricValue) {
+ public void trackObjectMetricValue(String eventName, ReadableMap data, Double metricValue, String environment) {
try {
- ldClient.track(eventName, toJsonObject(data), metricValue);
+ LDClient.getForMobileKey(environment).track(eventName, toJsonObject(data), metricValue);
} catch (Exception e) {
Timber.w(e);
}
}
@ReactMethod
- public void trackMetricValue(String eventName, Double metricValue) {
+ public void trackMetricValue(String eventName, Double metricValue, String environment) {
try {
- ldClient.track(eventName, new JsonPrimitive(""), metricValue);
+ LDClient.getForMobileKey(environment).track(eventName, new JsonPrimitive(""), metricValue);
} catch (Exception e) {
Timber.w(e);
}
}
- /**
- * Shuts down any network connections maintained by the client and puts the client in offline
- * mode.
- */
@ReactMethod
public void setOffline(Promise promise) {
try {
- ldClient.setOffline();
+ LDClient.get().setOffline();
promise.resolve(true);
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
- /**
- * Checks if the client is offline
- *
- * @param promise resolved with boolean value of whether client is offline, or rejected on error
- */
@ReactMethod
public void isOffline(Promise promise) {
try {
- boolean result = ldClient.isOffline();
+ boolean result = LDClient.get().isOffline();
promise.resolve(result);
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
- /**
- * Restores network connectivity for the client, if the client was previously in offline mode.
- */
@ReactMethod
public void setOnline(Promise promise) {
try {
- ldClient.setOnline();
+ LDClient.get().setOnline();
promise.resolve(true);
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
- /**
- * Checks if the client is initialized
- *
- * @param promise resolved with boolean value of whether client is initialized, or rejected on
- * error
- */
@ReactMethod
- public void isInitialized(Promise promise) {
- if (ldClient == null) {
- promise.resolve(false);
- return;
- }
-
+ public void isInitialized(String environment, Promise promise) {
try {
- boolean result = ldClient.isInitialized();
+ boolean result = LDClient.getForMobileKey(environment).isInitialized();
promise.resolve(result);
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
- /**
- * Triggers a background flush of pending events waiting to be sent to LaunchDarkly.
- */
@ReactMethod
public void flush() {
try {
- ldClient.flush();
+ LDClient.get().flush();
} catch (Exception e) {
Timber.w(e);
}
}
- /**
- * Triggers a background flush and then closes all connections to LaunchDarkly.
- */
@ReactMethod
public void close(Promise promise) {
try {
- ldClient.close();
+ LDClient.get().close();
promise.resolve(true);
} catch (Exception e) {
promise.reject(ERROR_CLOSE, e);
}
}
- /**
- * Calls LaunchDarkly's identify call that selects the user flags are pulled for, and tracking
- * events refer to.
- *
- * @param options User configuration ReadableMap (JS Object)
- * @param promise Resolved with null when identify complete or rejected with error
- */
@ReactMethod
public void identify(ReadableMap options, final Promise promise) {
final LDUser.Builder userBuilder = userBuild(options);
@@ -1089,7 +844,7 @@ public void identify(ReadableMap options, final Promise promise) {
@Override
public void run() {
try {
- ldClient.identify(userBuilder.build()).get();
+ LDClient.get().identify(userBuilder.build()).get();
promise.resolve(null);
} catch (InterruptedException e) {
Timber.w(e);
@@ -1107,48 +862,52 @@ public void run() {
}
@ReactMethod
- public void getConnectionMode(Promise promise) {
+ public void getConnectionMode(String environment,Promise promise) {
try {
- promise.resolve(ldClient.getConnectionInformation().getConnectionMode().name());
+ promise.resolve(LDClient.getForMobileKey(environment).getConnectionInformation().getConnectionMode().name());
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
@ReactMethod
- public void getLastSuccessfulConnection(Promise promise) {
+ public void getLastSuccessfulConnection(String environment,Promise promise) {
try {
- promise.resolve(ldClient.getConnectionInformation().getLastSuccessfulConnection().intValue());
+ promise.resolve(LDClient.getForMobileKey(environment).getConnectionInformation().getLastSuccessfulConnection().intValue());
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
@ReactMethod
- public void getLastFailedConnection(Promise promise) {
+ public void getLastFailedConnection(String environment,Promise promise) {
try {
- promise.resolve(ldClient.getConnectionInformation().getLastFailedConnection().intValue());
+ promise.resolve(LDClient.getForMobileKey(environment).getConnectionInformation().getLastFailedConnection().intValue());
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
@ReactMethod
- public void getLastFailure(Promise promise) {
+ public void getLastFailure(String environment,Promise promise) {
try {
- promise.resolve(ldClient.getConnectionInformation().getLastFailure().getFailureType().name());
+ promise.resolve(LDClient.getForMobileKey(environment).getConnectionInformation().getLastFailure().getFailureType().name());
} catch (Exception e) {
promise.reject(ERROR_UNKNOWN, e);
}
}
+ private String envConcat(String environment, String identifier) {
+ return environment.concat(";").concat(identifier);
+ }
+
@ReactMethod
- public void registerFeatureFlagListener(String flagKey) {
+ public void registerFeatureFlagListener(final String flagKey, final String environment) {
FeatureFlagChangeListener listener = new FeatureFlagChangeListener() {
@Override
public void onFeatureFlagChange(String flagKey) {
WritableMap result = Arguments.createMap();
- result.putString("flagKey", flagKey);
+ result.putString("flagKey", envConcat(environment, flagKey));
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
@@ -1157,7 +916,7 @@ public void onFeatureFlagChange(String flagKey) {
};
try {
- ldClient.registerFeatureFlagListener(flagKey, listener);
+ LDClient.getForMobileKey(environment).registerFeatureFlagListener(flagKey, listener);
listeners.put(flagKey, listener);
} catch (Exception e) {
Timber.w(e);
@@ -1165,10 +924,10 @@ public void onFeatureFlagChange(String flagKey) {
}
@ReactMethod
- public void unregisterFeatureFlagListener(String flagKey) {
+ public void unregisterFeatureFlagListener(String flagKey, String environment) {
try {
if (listeners.containsKey(flagKey)) {
- ldClient.unregisterFeatureFlagListener(flagKey, listeners.get(flagKey));
+ LDClient.getForMobileKey(environment).unregisterFeatureFlagListener(flagKey, listeners.get(flagKey));
listeners.remove(flagKey);
}
} catch (Exception e) {
@@ -1177,12 +936,13 @@ public void unregisterFeatureFlagListener(String flagKey) {
}
@ReactMethod
- public void registerCurrentConnectionModeListener(String listenerId) {
+ public void registerCurrentConnectionModeListener(final String listenerId, final String environment) {
LDStatusListener listener = new LDStatusListener() {
@Override
public void onConnectionModeChanged(ConnectionInformation connectionInfo) {
WritableMap result = Arguments.createMap();
result.putString("connectionMode", gson.toJson(connectionInfo));
+ result.putString("listenerId", envConcat(environment, listenerId));
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
@@ -1194,7 +954,7 @@ public void onInternalFailure(LDFailure ldFailure) {}
};
try {
- ldClient.registerStatusListener(listener);
+ LDClient.getForMobileKey(environment).registerStatusListener(listener);
connectionModeListeners.put(listenerId, listener);
} catch (Exception e) {
Timber.w(e);
@@ -1202,10 +962,10 @@ public void onInternalFailure(LDFailure ldFailure) {}
}
@ReactMethod
- public void unregisterCurrentConnectionModeListener(String listenerId) {
+ public void unregisterCurrentConnectionModeListener(String listenerId, String environment) {
try {
if (connectionModeListeners.containsKey(listenerId)) {
- ldClient.unregisterStatusListener(connectionModeListeners.get(listenerId));
+ LDClient.getForMobileKey(environment).unregisterStatusListener(connectionModeListeners.get(listenerId));
connectionModeListeners.remove(listenerId);
}
} catch (Exception e) {
@@ -1214,12 +974,13 @@ public void unregisterCurrentConnectionModeListener(String listenerId) {
}
@ReactMethod
- public void registerAllFlagsListener(String listenerId) {
+ public void registerAllFlagsListener(final String listenerId, final String environment) {
LDAllFlagsListener listener = new LDAllFlagsListener() {
@Override
public void onChange(List flagKeys) {
WritableMap result = Arguments.createMap();
result.putString("flagKeys", gson.toJson(flagKeys));
+ result.putString("listenerId", envConcat(environment, listenerId));
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
@@ -1228,7 +989,7 @@ public void onChange(List flagKeys) {
};
try {
- ldClient.registerAllFlagsListener(listener);
+ LDClient.getForMobileKey(environment).registerAllFlagsListener(listener);
allFlagsListeners.put(listenerId, listener);
} catch (Exception e) {
Timber.w(e);
@@ -1236,10 +997,10 @@ public void onChange(List flagKeys) {
}
@ReactMethod
- public void unregisterAllFlagsListener(String listenerId) {
+ public void unregisterAllFlagsListener(String listenerId, String environment) {
try {
if (allFlagsListeners.containsKey(listenerId)) {
- ldClient.unregisterAllFlagsListener(allFlagsListeners.get(listenerId));
+ LDClient.getForMobileKey(environment).unregisterAllFlagsListener(allFlagsListeners.get(listenerId));
allFlagsListeners.remove(listenerId);
}
} catch (Exception e) {
@@ -1247,15 +1008,6 @@ public void unregisterAllFlagsListener(String listenerId) {
}
}
- /**
- * Convert a ReadableMap into a JsonObject
- *
- * This will recursively convert internal ReadableMaps and ReadableArrays into JsonObjects and
- * JsonArrays.
- *
- * @param readableMap A ReadableMap to be converted to a JsonObject
- * @return A JsonObject containing the converted elements from the ReadableMap.
- */
private static JsonObject toJsonObject(ReadableMap readableMap) {
if (readableMap == null)
return null;
@@ -1293,15 +1045,6 @@ private static JsonObject toJsonObject(ReadableMap readableMap) {
return jsonObject;
}
- /**
- * Convert a ReadableArray into a JsonArray
- *
- * This will recursively convert internal ReadableMaps and ReadableArrays into JsonObjects and
- * JsonArrays.
- *
- * @param readableArray A ReadableArray to be converted to a JsonArray
- * @return A JsonArray containing the converted elements from the ReadableArray
- */
private static JsonArray toJsonArray(ReadableArray readableArray) {
if (readableArray == null)
return null;
@@ -1336,15 +1079,6 @@ private static JsonArray toJsonArray(ReadableArray readableArray) {
return jsonArray;
}
- /**
- * Convert a JsonArray into a WritableArray
- *
- * This will recursively convert internal JsonObjects and JsonArrays into WritableMaps and
- * WritableArrays.
- *
- * @param jsonArray A JsonArray to be converted into a WritableArray
- * @return A WritableArray containing converted elements from the JsonArray
- */
private static WritableArray fromJsonArray(JsonArray jsonArray) {
if (jsonArray == null)
return null;
@@ -1371,16 +1105,6 @@ private static WritableArray fromJsonArray(JsonArray jsonArray) {
return result;
}
-
- /**
- * Convert a JsonObject into a WritableMap
- *
- * This will recursively convert internal JsonObjects and JsonArrays into WritableMaps and
- * WritableArrays.
- *
- * @param jsonObject A JsonObject to be converted into a WritableMap
- * @return A WritableMap containing converted elements from the jsonObject
- */
private static WritableMap fromJsonObject(JsonObject jsonObject) {
if (jsonObject == null)
return null;
@@ -1407,32 +1131,10 @@ private static WritableMap fromJsonObject(JsonObject jsonObject) {
return result;
}
- /**
- * A support interface for defining how a ConfigEntryType is read and converted from a
- * ReadableMap of configuration entries.
- *
- * @param The returned type of a value read from the config entry.
- */
interface ConvertFromReadable {
- /**
- * Reads a config entry from map by key and converts to the appropriate return type of the
- * ConfigEntryType.
- *
- * @param map A ReadableMap to get the raw config entry
- * @param key The key to look up the config entry from the map
- * @return An appropriate return value for the ConfigEntryType
- */
T getFromMap(ReadableMap map, String key);
}
- /**
- * An enum for the supported types of config entries.
- *
- *
- * Each type of config entry has a base ReadableType for checking that a ReadableMap contains an
- * entry of the correct type, as well as an implementation of ConvertFromReadable for retrieving
- * and converting a ReadableMap entry into a non base type for configuration processing.
- */
enum ConfigEntryType implements ConvertFromReadable {
String(ReadableType.String) {
public String getFromMap(ReadableMap map, String key) {
@@ -1464,6 +1166,11 @@ public Boolean getFromMap(ReadableMap map, String key) {
return map.getBoolean(key);
}
},
+ Map(ReadableType.Map) {
+ public Map getFromMap(ReadableMap map, String key) {
+ return map.getMap(key).toHashMap();
+ }
+ },
StringSet(ReadableType.Array) {
public Set getFromMap(ReadableMap map, String key) {
ReadableArray array = map.getArray(key);
@@ -1488,13 +1195,6 @@ ReadableType getReadableType() {
}
}
- /**
- * A helper for looking up a method from a Java class (reflection).
- *
- * @param cls The class to look up the method from
- * @param methodName The name of the method to look up
- * @return The looked up method (or null)
- */
private static Method findSetter(Class cls, String methodName) {
for (Method method : cls.getMethods()) {
if (method.getName().equals(methodName) && method.getParameterTypes().length == 1)
diff --git a/index.d.ts b/index.d.ts
index 1bd1d8e..860e678 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -161,6 +161,11 @@ declare module 'launchdarkly-react-native-client-sdk' {
*/
diagnosticRecordingIntervalMillis?: number;
+ /**
+ * The mapping of environment names as keys to mobile keys for each environment as values.
+ */
+ secondaryMobileKeys?: Record;
+
/**
* Whether to treat all user attributes as private for event reporting for all users.
* The SDK will not include private attribute values in analytics events, but private attribute names will be sent.
@@ -179,6 +184,13 @@ declare module 'launchdarkly-react-native-client-sdk' {
*/
key: string;
+ /**
+ * The secondary key for the user. See the
+ * [documentation](https://docs.launchdarkly.com/home/managing-flags/targeting-users#percentage-rollout-logic)
+ * for more information on it's use for percentage rollout bucketing.
+ */
+ secondary?: string;
+
/**
* The user's name.
*
@@ -434,10 +446,12 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing the flag's value.
*/
- boolVariation(flagKey: string, defaultValue: boolean): Promise;
+ boolVariation(flagKey: string, defaultValue: boolean, environment?: string): Promise;
/**
* Determines the variation of an integer feature flag for the current user.
@@ -446,10 +460,12 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing the flag's value.
*/
- intVariation(flagKey: string, defaultValue: number): Promise;
+ intVariation(flagKey: string, defaultValue: number, environment?: string): Promise;
/**
* Determines the variation of a floating-point feature flag for the current user.
@@ -458,10 +474,12 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing the flag's value.
*/
- floatVariation(flagKey: string, defaultValue: number): Promise;
+ floatVariation(flagKey: string, defaultValue: number, environment?: string): Promise;
/**
* Determines the variation of a string feature flag for the current user.
@@ -470,10 +488,12 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing the flag's value.
*/
- stringVariation(flagKey: string, defaultValue: string): Promise;
+ stringVariation(flagKey: string, defaultValue: string, environment?: string): Promise;
/**
* Determines the variation of a JSON feature flag for the current user.
@@ -482,12 +502,15 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing the flag's value.
*/
jsonVariation(
flagKey: string,
defaultValue: Record,
+ environment?: string
): Promise>;
/**
@@ -503,12 +526,15 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing an [[LDEvaluationDetail]] object containing the value and explanation.
*/
boolVariationDetail(
flagKey: string,
defaultValue: boolean,
+ environment?: string
): Promise>;
/**
@@ -524,12 +550,15 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing an [[LDEvaluationDetail]] object containing the value and explanation.
*/
intVariationDetail(
flagKey: string,
defaultValue: number,
+ environment?: string
): Promise>;
/**
@@ -545,12 +574,15 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing an [[LDEvaluationDetail]] object containing the value and explanation.
*/
floatVariationDetail(
flagKey: string,
defaultValue: number,
+ environment?: string
): Promise>;
/**
@@ -566,12 +598,15 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing an [[LDEvaluationDetail]] object containing the value and explanation.
*/
stringVariationDetail(
flagKey: string,
defaultValue: string,
+ environment?: string
): Promise>;
/**
@@ -587,24 +622,29 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The unique key of the feature flag.
* @param defaultValue
* The default value of the flag, to be used if the value is not available from LaunchDarkly.
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing an [[LDEvaluationDetail]] object containing the value and explanation.
*/
jsonVariationDetail(
flagKey: string,
defaultValue: Record,
+ environment?: string
): Promise>>;
/**
* Returns a map of all available flags to the current user's values.
*
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise containing an object in which each key is a feature flag key and each value is the flag value.
* The promise will be rejected if the SDK has not yet completed initialization.
* Note that there is no way to specify a default value for each flag as there is with the
* `*Variation` methods, so any flag that cannot be evaluated will have a null value.
*/
- allFlags(): Promise;
+ allFlags(environment?: string): Promise;
/**
* Track events to use in goals or A/B tests.
@@ -615,8 +655,10 @@ declare module 'launchdarkly-react-native-client-sdk' {
* Optional additional information to associate with the event.
* @param metricValue
* Optional numeric value to attach to the tracked event
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
*/
- track(eventName: string, data?: any, metricValue?: number): void;
+ track(eventName: string, data?: any, metricValue?: number, environment?: string): void;
/**
* Checks whether the client has been put into offline mode. This is true only if [[setOffline]]
@@ -659,10 +701,12 @@ declare module 'launchdarkly-react-native-client-sdk' {
*
* This function only works when running in Android. On iOS, this function will return a rejected promise.
*
+ * @param environment
+ * Optional environment name to obtain the result from the corresponding secondary environment
* @returns
* A promise contianing true if the client is initialized or offline
*/
- isInitialized(): Promise;
+ isInitialized(environment?: string): Promise;
/**
* Flushes all pending analytics events.
@@ -697,10 +741,13 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The flag key to attach the callback to
* @param callback
* The callback to attach to the flag key
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
*/
registerFeatureFlagListener(
flagKey: string,
callback: (flagKey: string) => void,
+ environment?: string
): void;
/**
@@ -710,10 +757,13 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The flag key to remove the callback from
* @param callback
* The callback to remove from the flag key
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
*/
unregisterFeatureFlagListener(
flagKey: string,
callback: (flagKey: string) => void,
+ environment?: string
): void;
/**
@@ -730,30 +780,36 @@ declare module 'launchdarkly-react-native-client-sdk' {
* - `'SHUTDOWN'`: (Android specific enum value) The shutdown state indicates the SDK has been permanently shutdown as a result of a call to close().
* - `'ESTABLISHING_STREAMING_CONNECTION'`: (iOS specific enum value) The SDK is attempting to connect to LaunchDarkly by streaming.
*
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
* @returns
* A promise containing a LDConnectionMode enum value representing the status of the connection to LaunchDarkly.
*/
- getConnectionMode(): Promise;
+ getConnectionMode(environment?: string): Promise;
/**
* Returns the most recent successful flag cache update in millis from the epoch
* or null if flags have never been retrieved.
*
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
* @returns
* A promise containing a number representing the status of the connection to LaunchDarkly,
* or null if a successful connection has yet to be established.
*/
- getLastSuccessfulConnection(): Promise;
+ getLastSuccessfulConnection(environment?: string): Promise;
/**
* Most recent unsuccessful flag cache update attempt in millis from the epoch
* or null if flag update has never been attempted.
*
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
* @returns
* A promise containing a number representing the status of the connection to LaunchDarkly,
* or null if a failed connection has yet to occur.
*/
- getLastFailedConnection(): Promise;
+ getLastFailedConnection(environment?: string): Promise;
/**
* Returns the most recent connection failure reason or null.
@@ -769,11 +825,13 @@ declare module 'launchdarkly-react-native-client-sdk' {
* - `'NETWORK_FAILURE'`: (Android specific enum value) A network request for polling, or the EventSource stream reported a failure.
* - `'INVALID_RESPONSE_BODY'`: (Android specific enum value) A response body received either through polling or streaming was unable to be parsed.
*
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
* @returns
* A promise containing a LDFailureReason enum value representing the reason for the most recently failed
* connection to LaunchDarkly, or null if a failed connection has yet to occur.
*/
- getLastFailure(): Promise;
+ getLastFailure(environment?: string): Promise;
/**
* Registers a callback to be called on connection status updates.
@@ -782,19 +840,24 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The listener to be called on a connection status update
* @param callback
* The callback to attach to the connection status update
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
*/
registerCurrentConnectionModeListener(
listenerId: string,
callback: (connectionMode: string) => void,
+ environment?: string
): void;
/**
* Unregisters a callback so that it will no longer be called on connection status updates.
*
* @param listenerId
- * The listener to remoce the callback from
+ * The listener to remove the callback from
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
*/
- unregisterCurrentConnectionModeListener(listenerId: string): void;
+ unregisterCurrentConnectionModeListener(listenerId: string, environment?: string): void;
/**
* Registers a callback to be called when a flag update is processed by the SDK.
@@ -803,10 +866,13 @@ declare module 'launchdarkly-react-native-client-sdk' {
* The listener to be called when a flag update is processed
* @param callback
* The callback to attach to the flag update
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
*/
registerAllFlagsListener(
listenerId: string,
callback: (updatedFlags: string[]) => void,
+ environment?: string
): void;
/**
@@ -814,8 +880,10 @@ declare module 'launchdarkly-react-native-client-sdk' {
*
* @param listenerId
* The listener to be removed
+ * @param environment
+ * Optional string to execute the function in a different environment than the default.
*/
- unregisterAllFlagsListener(listenerId: string): void;
+ unregisterAllFlagsListener(listenerId: string, environment?: string): void;
}
}
diff --git a/index.js b/index.js
index b443f29..9dcea3d 100644
--- a/index.js
+++ b/index.js
@@ -37,138 +37,150 @@ export default class LDClient {
}
}
- boolVariation(flagKey, defaultValue) {
+ boolVariation(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.boolVariation(flagKey);
+ return LaunchdarklyReactNativeClient.boolVariation(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.boolVariationDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.boolVariationDefaultValue(flagKey, defaultValue, env);
}
}
- intVariation(flagKey, defaultValue) {
+ intVariation(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.intVariation(flagKey);
+ return LaunchdarklyReactNativeClient.intVariation(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.intVariationDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.intVariationDefaultValue(flagKey, defaultValue, env);
}
}
- floatVariation(flagKey, defaultValue) {
+ floatVariation(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.floatVariation(flagKey);
+ return LaunchdarklyReactNativeClient.floatVariation(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.floatVariationDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.floatVariationDefaultValue(flagKey, defaultValue, env);
}
}
- stringVariation(flagKey, defaultValue) {
+ stringVariation(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.stringVariation(flagKey);
+ return LaunchdarklyReactNativeClient.stringVariation(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.stringVariationDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.stringVariationDefaultValue(flagKey, defaultValue, env);
}
}
- jsonVariation(flagKey, defaultValue) {
+ jsonVariation(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.jsonVariationNone(flagKey);
+ return LaunchdarklyReactNativeClient.jsonVariationNone(flagKey, env);
} else if (typeof defaultValue === 'number') {
- return LaunchdarklyReactNativeClient.jsonVariationNumber(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationNumber(flagKey, defaultValue, env);
} else if (typeof defaultValue === 'boolean') {
- return LaunchdarklyReactNativeClient.jsonVariationBool(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationBool(flagKey, defaultValue, env);
} else if (typeof defaultValue === 'string') {
- return LaunchdarklyReactNativeClient.jsonVariationString(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationString(flagKey, defaultValue, env);
} else if (Array.isArray(defaultValue)) {
- return LaunchdarklyReactNativeClient.jsonVariationArray(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationArray(flagKey, defaultValue, env);
} else {
// Should be an object
- return LaunchdarklyReactNativeClient.jsonVariationObject(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationObject(flagKey, defaultValue, env);
}
}
- boolVariationDetail(flagKey, defaultValue) {
+ boolVariationDetail(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.boolVariationDetail(flagKey);
+ return LaunchdarklyReactNativeClient.boolVariationDetail(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.boolVariationDetailDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.boolVariationDetailDefaultValue(flagKey, defaultValue, env);
}
}
- intVariationDetail(flagKey, defaultValue) {
+ intVariationDetail(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.intVariationDetail(flagKey);
+ return LaunchdarklyReactNativeClient.intVariationDetail(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.intVariationDetailDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.intVariationDetailDefaultValue(flagKey, defaultValue, env);
}
}
- floatVariationDetail(flagKey, defaultValue) {
+ floatVariationDetail(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.floatVariationDetail(flagKey);
+ return LaunchdarklyReactNativeClient.floatVariationDetail(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.floatVariationDetailDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.floatVariationDetailDefaultValue(flagKey, defaultValue, env);
}
}
- stringVariationDetail(flagKey, defaultValue) {
+ stringVariationDetail(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.stringVariationDetail(flagKey);
+ return LaunchdarklyReactNativeClient.stringVariationDetail(flagKey, env);
} else {
- return LaunchdarklyReactNativeClient.stringVariationDetailDefaultValue(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.stringVariationDetailDefaultValue(flagKey, defaultValue, env);
}
}
- jsonVariationDetail(flagKey, defaultValue) {
+ jsonVariationDetail(flagKey, defaultValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (defaultValue == undefined) {
- return LaunchdarklyReactNativeClient.jsonVariationDetailNone(flagKey);
+ return LaunchdarklyReactNativeClient.jsonVariationDetailNone(flagKey, env);
} else if (typeof defaultValue === 'number') {
- return LaunchdarklyReactNativeClient.jsonVariationDetailNumber(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationDetailNumber(flagKey, defaultValue, env);
} else if (typeof defaultValue === 'boolean') {
- return LaunchdarklyReactNativeClient.jsonVariationDetailBool(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationDetailBool(flagKey, defaultValue, env);
} else if (typeof defaultValue === 'string') {
- return LaunchdarklyReactNativeClient.jsonVariationDetailString(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationDetailString(flagKey, defaultValue, env);
} else if (Array.isArray(defaultValue)) {
- return LaunchdarklyReactNativeClient.jsonVariationDetailArray(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationDetailArray(flagKey, defaultValue, env);
} else {
// Should be an object
- return LaunchdarklyReactNativeClient.jsonVariationDetailObject(flagKey, defaultValue);
+ return LaunchdarklyReactNativeClient.jsonVariationDetailObject(flagKey, defaultValue, env);
}
}
- allFlags() {
- return LaunchdarklyReactNativeClient.allFlags();
+ allFlags(environment) {
+ const env = environment !== undefined ? environment : "default";
+ return LaunchdarklyReactNativeClient.allFlags(env);
}
- track(eventName, data, metricValue) {
+ track(eventName, data, metricValue, environment) {
+ const env = environment !== undefined ? environment : "default";
if (metricValue) {
if (data === null || typeof data === 'undefined') {
- LaunchdarklyReactNativeClient.trackMetricValue(eventName, metricValue);
+ LaunchdarklyReactNativeClient.trackMetricValue(eventName, metricValue, env);
} else if (typeof data === 'number') {
- LaunchdarklyReactNativeClient.trackNumberMetricValue(eventName, data, metricValue);
+ LaunchdarklyReactNativeClient.trackNumberMetricValue(eventName, data, metricValue, env);
} else if (typeof data === 'boolean') {
- LaunchdarklyReactNativeClient.trackBoolMetricValue(eventName, data, metricValue);
+ LaunchdarklyReactNativeClient.trackBoolMetricValue(eventName, data, metricValue, env);
} else if (typeof data === 'string') {
- LaunchdarklyReactNativeClient.trackStringMetricValue(eventName, data, metricValue);
+ LaunchdarklyReactNativeClient.trackStringMetricValue(eventName, data, metricValue, env);
} else if (Array.isArray(data)) {
- LaunchdarklyReactNativeClient.trackArrayMetricValue(eventName, data, metricValue);
+ LaunchdarklyReactNativeClient.trackArrayMetricValue(eventName, data, metricValue, env);
} else {
// should be an object
- LaunchdarklyReactNativeClient.trackObjectMetricValue(eventName, data, metricValue);
+ LaunchdarklyReactNativeClient.trackObjectMetricValue(eventName, data, metricValue, env);
}
} else {
if (data === null || typeof data === 'undefined') {
- LaunchdarklyReactNativeClient.track(eventName);
+ LaunchdarklyReactNativeClient.track(eventName, env);
} else if (typeof data === 'number') {
- LaunchdarklyReactNativeClient.trackNumber(eventName, data);
+ LaunchdarklyReactNativeClient.trackNumber(eventName, data, env);
} else if (typeof data === 'boolean') {
- LaunchdarklyReactNativeClient.trackBool(eventName, data);
+ LaunchdarklyReactNativeClient.trackBool(eventName, data, env);
} else if (typeof data === 'string') {
- LaunchdarklyReactNativeClient.trackString(eventName, data);
+ LaunchdarklyReactNativeClient.trackString(eventName, data, env);
} else if (Array.isArray(data)) {
- LaunchdarklyReactNativeClient.trackArray(eventName, data);
+ LaunchdarklyReactNativeClient.trackArray(eventName, data, env);
} else {
// should be an object
- LaunchdarklyReactNativeClient.trackObject(eventName, data);
+ LaunchdarklyReactNativeClient.trackObject(eventName, data, env);
}
}
}
@@ -185,8 +197,9 @@ export default class LDClient {
return LaunchdarklyReactNativeClient.setOnline();
}
- isInitialized() {
- return LaunchdarklyReactNativeClient.isInitialized();
+ isInitialized(environment) {
+ const env = environment !== undefined ? environment : "default";
+ return LaunchdarklyReactNativeClient.isInitialized(env);
}
flush() {
@@ -219,94 +232,121 @@ export default class LDClient {
_allFlagsUpdateListener(changedFlags) {
const flagKeys = changedFlags.flagKeys;
- let listeners = Object.values(this.allFlagsListeners);
- for (const listener of listeners) {
- listener(flagKeys);
+ const listenerId = changedFlags.listenerId;
+ for (const [key, value] of Object.entries(this.allFlagsListeners)) {
+ if (key == listenerId) {
+ key(flagKeys);
+ }
}
}
_connectionModeUpdateListener(connectionStatus) {
const connectionMode = connectionStatus.connectionMode;
- let listeners = Object.values(this.connectionModeListeners);
- for (const listener of listeners) {
- listener(connectionMode);
+ const listenerId = connectionStatus.listenerId;
+ for (const [key, value] of Object.entries(this.connectionModeListeners)) {
+ if (key == listenerId) {
+ key(connectionMode);
+ }
}
}
- registerFeatureFlagListener(flagKey, callback) {
+ _envConcat(env, flagKey) {
+ return env.concat(";", flagKey)
+ }
+
+ registerFeatureFlagListener(flagKey, callback, environment) {
if (typeof callback !== "function") {
return;
}
+ const env = environment !== undefined ? environment : "default";
+ const multiFlagKey = this._envConcat(env, flagKey);
- if (this.flagListeners.hasOwnProperty(flagKey)) {
- this.flagListeners[flagKey].push(callback);
+ if (this.flagListeners.hasOwnProperty(multiFlagKey)) {
+ this.flagListeners[multiFlagKey].push(callback);
} else {
- this.flagListeners[flagKey] = [callback];
+ this.flagListeners[multiFlagKey] = [callback];
- LaunchdarklyReactNativeClient.registerFeatureFlagListener(flagKey);
+ LaunchdarklyReactNativeClient.registerFeatureFlagListener(flagKey, env);
}
}
- unregisterFeatureFlagListener(flagKey, callback) {
- if (!this.flagListeners.hasOwnProperty(flagKey))
+ unregisterFeatureFlagListener(flagKey, callback, environment) {
+ const env = environment !== undefined ? environment : "default";
+ const multiFlagKey = this._envConcat(env, flagKey);
+ if (!this.flagListeners.hasOwnProperty(multiFlagKey)) {
return;
+ }
- this.flagListeners[flagKey] =
- this.flagListeners[flagKey].filter(listener => listener != callback);
+ this.flagListeners[multiFlagKey] =
+ this.flagListeners[multiFlagKey].filter(listener => listener != callback);
- if (this.flagListeners[flagKey].length == 0) {
- LaunchdarklyReactNativeClient.unregisterFeatureFlagListener(flagKey);
- delete this.flagListeners[flagKey];
+ if (this.flagListeners[multiFlagKey].length == 0) {
+ LaunchdarklyReactNativeClient.unregisterFeatureFlagListener(flagKey, env);
+ delete this.flagListeners[multiFlagKey];
}
}
- registerCurrentConnectionModeListener(listenerId, callback) {
+ registerCurrentConnectionModeListener(listenerId, callback, environment) {
if (typeof callback !== "function") {
return;
}
+ const env = environment !== undefined ? environment : "default";
+ const multiListenerId = this._envConcat(env, flagKey);
- this.connectionModeListeners[listenerId] = callback;
- LaunchdarklyReactNativeClient.registerCurrentConnectionModeListener(listenerId);
+ this.connectionModeListeners[multiListenerId] = callback;
+ LaunchdarklyReactNativeClient.registerCurrentConnectionModeListener(listenerId, env);
}
- unregisterCurrentConnectionModeListener(listenerId) {
- if (!this.connectionModeListeners.hasOwnProperty(listenerId))
+ unregisterCurrentConnectionModeListener(listenerId, environment) {
+ const env = environment !== undefined ? environment : "default";
+ const multiListenerId = this._envConcat(env, flagKey);
+ if (!this.connectionModeListeners.hasOwnProperty(multiListenerId)) {
return;
+ }
- LaunchdarklyReactNativeClient.unregisterCurrentConnectionModeListener(listenerId);
- delete this.connectionModeListeners[listenerId];
+ LaunchdarklyReactNativeClient.unregisterCurrentConnectionModeListener(listenerId, env);
+ delete this.connectionModeListeners[multiListenerId];
}
- registerAllFlagsListener(listenerId, callback) {
+ registerAllFlagsListener(listenerId, callback, environment) {
if (typeof callback !== "function") {
return;
}
+ const env = environment !== undefined ? environment : "default";
+ const multiListenerId = this._envConcat(env, flagKey);
- this.allFlagsListeners[listenerId] = callback;
- LaunchdarklyReactNativeClient.registerAllFlagsListener(listenerId);
+ this.allFlagsListeners[multiListenerId] = callback;
+ LaunchdarklyReactNativeClient.registerAllFlagsListener(listenerId, env);
}
- unregisterAllFlagsListener(listenerId) {
- if (!this.allFlagsListeners.hasOwnProperty(listenerId))
+ unregisterAllFlagsListener(listenerId, environment) {
+ const env = environment !== undefined ? environment : "default";
+ const multiListenerId = this._envConcat(env, flagKey);
+ if (!this.allFlagsListeners.hasOwnProperty(multiListenerId)) {
return;
+ }
- LaunchdarklyReactNativeClient.unregisterAllFlagsListener(listenerId);
- delete this.allFlagsListeners[listenerId];
+ LaunchdarklyReactNativeClient.unregisterAllFlagsListener(listenerId, env);
+ delete this.allFlagsListeners[multiListenerId];
}
- getConnectionMode() {
- return LaunchdarklyReactNativeClient.getConnectionMode();
+ getConnectionMode(environment) {
+ const env = environment !== undefined ? environment : "default";
+ return LaunchdarklyReactNativeClient.getConnectionMode(env);
}
- getLastSuccessfulConnection() {
- return LaunchdarklyReactNativeClient.getLastSuccessfulConnection();
+ getLastSuccessfulConnection(environment) {
+ const env = environment !== undefined ? environment : "default";
+ return LaunchdarklyReactNativeClient.getLastSuccessfulConnection(env);
}
- getLastFailedConnection() {
- return LaunchdarklyReactNativeClient.getLastFailedConnection();
+ getLastFailedConnection(environment) {
+ const env = environment !== undefined ? environment : "default";
+ return LaunchdarklyReactNativeClient.getLastFailedConnection(env);
}
- getLastFailure() {
- return LaunchdarklyReactNativeClient.getLastFailure();
+ getLastFailure(environment) {
+ const env = environment !== undefined ? environment : "default";
+ return LaunchdarklyReactNativeClient.getLastFailure(env);
}
}
diff --git a/ios/LaunchdarklyReactNativeClient.swift b/ios/LaunchdarklyReactNativeClient.swift
index f3966b8..0dd1488 100644
--- a/ios/LaunchdarklyReactNativeClient.swift
+++ b/ios/LaunchdarklyReactNativeClient.swift
@@ -48,7 +48,8 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
}
} else {
LDClient.start(config: config!, user: user, completion: {() -> Void in
- resolve(nil)})
+ resolve(nil)
+ })
}
}
}
@@ -134,6 +135,10 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
ldConfig.diagnosticRecordingInterval = TimeInterval(config["diagnosticRecordingIntervalMillis"] as! Float / 1000)
}
+ if config["secondaryMobileKeys"] != nil {
+ try! ldConfig.setSecondaryMobileKeys(config["secondaryMobileKeys"] as! [String: String])
+ }
+
if config["allUserAttributesPrivate"] != nil {
ldConfig.allUserAttributesPrivate = config["allUserAttributesPrivate"] as! Bool
}
@@ -146,6 +151,10 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
private func userBuild(userDict: NSDictionary) -> LDUser? {
var user = LDUser()
user.key = userDict["key"] as! String
+
+ if userDict["secondary"] != nil {
+ user.secondary = userDict["secondary"] as? String
+ }
if userDict["name"] != nil {
user.name = userDict["name"] as? String
@@ -190,253 +199,253 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
return user
}
- @objc func boolVariationDefaultValue(_ flagKey: String, defaultValue: ObjCBool, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue.boolValue) as Bool)
+ @objc func boolVariationDefaultValue(_ flagKey: String, defaultValue: ObjCBool, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue.boolValue) as Bool)
}
- @objc func intVariationDefaultValue(_ flagKey: String, defaultValue: Int, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue) as Int)
+ @objc func intVariationDefaultValue(_ flagKey: String, defaultValue: Int, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue) as Int)
}
- @objc func floatVariationDefaultValue(_ flagKey: String, defaultValue: CGFloat, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: Double(defaultValue)) as Double)
+ @objc func floatVariationDefaultValue(_ flagKey: String, defaultValue: CGFloat, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: Double(defaultValue)) as Double)
}
- @objc func stringVariationDefaultValue(_ flagKey: String, defaultValue: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue) as String)
+ @objc func stringVariationDefaultValue(_ flagKey: String, defaultValue: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue) as String)
}
- @objc func boolVariation(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let boolFlagValue: Bool? = LDClient.get()!.variation(forKey: flagKey)
+ @objc func boolVariation(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let boolFlagValue: Bool? = LDClient.get(environment: environment)!.variation(forKey: flagKey)
resolve(boolFlagValue)
}
- @objc func intVariation(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let intFlagValue: Int? = LDClient.get()!.variation(forKey: flagKey)
+ @objc func intVariation(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let intFlagValue: Int? = LDClient.get(environment: environment)!.variation(forKey: flagKey)
resolve(intFlagValue)
}
- @objc func floatVariation(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let floatFlagValue: Double? = LDClient.get()!.variation(forKey: flagKey)
+ @objc func floatVariation(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let floatFlagValue: Double? = LDClient.get(environment: environment)!.variation(forKey: flagKey)
resolve(floatFlagValue)
}
- @objc func stringVariation(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let stringFlagValue: String? = LDClient.get()!.variation(forKey: flagKey)
+ @objc func stringVariation(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let stringFlagValue: String? = LDClient.get(environment: environment)!.variation(forKey: flagKey)
resolve(stringFlagValue)
}
- @objc func jsonVariationNone(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let jsonFlagValue: Dictionary? = LDClient.get()!.variation(forKey: flagKey)
+ @objc func jsonVariationNone(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let jsonFlagValue: Dictionary? = LDClient.get(environment: environment)!.variation(forKey: flagKey)
resolve(jsonFlagValue)
}
- @objc func jsonVariationNumber(_ flagKey: String, defaultValue: Double, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue) as Double)
+ @objc func jsonVariationNumber(_ flagKey: String, defaultValue: Double, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue) as Double)
}
- @objc func jsonVariationBool(_ flagKey: String, defaultValue: Bool, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue) as Bool)
+ @objc func jsonVariationBool(_ flagKey: String, defaultValue: Bool, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue) as Bool)
}
- @objc func jsonVariationString(_ flagKey: String, defaultValue: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue) as String)
+ @objc func jsonVariationString(_ flagKey: String, defaultValue: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue) as String)
}
- @objc func jsonVariationArray(_ flagKey: String, defaultValue: Array, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue) as Array)
+ @objc func jsonVariationArray(_ flagKey: String, defaultValue: Array, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue) as Array)
}
- @objc func jsonVariationObject(_ flagKey: String, defaultValue: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.variation(forKey: flagKey, defaultValue: defaultValue.swiftDictionary) as NSDictionary)
+ @objc func jsonVariationObject(_ flagKey: String, defaultValue: NSDictionary, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.variation(forKey: flagKey, defaultValue: defaultValue.swiftDictionary) as NSDictionary)
}
- @objc func boolVariationDetailDefaultValue(_ flagKey: String, defaultValue: ObjCBool, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue.boolValue)
+ @objc func boolVariationDetailDefaultValue(_ flagKey: String, defaultValue: ObjCBool, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue.boolValue)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func intVariationDetailDefaultValue(_ flagKey: String, defaultValue: Int, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
+ @objc func intVariationDetailDefaultValue(_ flagKey: String, defaultValue: Int, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func floatVariationDetailDefaultValue(_ flagKey: String, defaultValue: CGFloat, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: Double(defaultValue))
+ @objc func floatVariationDetailDefaultValue(_ flagKey: String, defaultValue: CGFloat, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: Double(defaultValue))
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func stringVariationDetailDefaultValue(_ flagKey: String, defaultValue: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
+ @objc func stringVariationDetailDefaultValue(_ flagKey: String, defaultValue: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func boolVariationDetail(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail: LDEvaluationDetail = LDClient.get()!.variationDetail(forKey: flagKey)
+ @objc func boolVariationDetail(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail: LDEvaluationDetail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func intVariationDetail(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail: LDEvaluationDetail = LDClient.get()!.variationDetail(forKey: flagKey)
+ @objc func intVariationDetail(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail: LDEvaluationDetail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func floatVariationDetail(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail: LDEvaluationDetail = LDClient.get()!.variationDetail(forKey: flagKey)
+ @objc func floatVariationDetail(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail: LDEvaluationDetail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func stringVariationDetail(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail: LDEvaluationDetail = LDClient.get()!.variationDetail(forKey: flagKey)
+ @objc func stringVariationDetail(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail: LDEvaluationDetail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func jsonVariationDetailNone(_ flagKey: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail: LDEvaluationDetail?> = LDClient.get()!.variationDetail(forKey: flagKey)
+ @objc func jsonVariationDetailNone(_ flagKey: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail: LDEvaluationDetail?> = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func jsonVariationDetailNumber(_ flagKey: String, defaultValue: Double, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
+ @objc func jsonVariationDetailNumber(_ flagKey: String, defaultValue: Double, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func jsonVariationDetailBool(_ flagKey: String, defaultValue: Bool, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
+ @objc func jsonVariationDetailBool(_ flagKey: String, defaultValue: Bool, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func jsonVariationDetailString(_ flagKey: String, defaultValue: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
+ @objc func jsonVariationDetailString(_ flagKey: String, defaultValue: String, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func jsonVariationDetailArray(_ flagKey: String, defaultValue: Array, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
+ @objc func jsonVariationDetailArray(_ flagKey: String, defaultValue: Array, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func jsonVariationDetailObject(_ flagKey: String, defaultValue: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let detail = LDClient.get()!.variationDetail(forKey: flagKey, defaultValue: defaultValue.swiftDictionary)
+ @objc func jsonVariationDetailObject(_ flagKey: String, defaultValue: NSDictionary, environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let detail = LDClient.get(environment: environment)!.variationDetail(forKey: flagKey, defaultValue: defaultValue.swiftDictionary)
let jsonObject: NSDictionary = [
- "value": (detail.value as Any?) ?? NSNull(),
- "variationIndex": (detail.variationIndex as Any?) ?? NSNull(),
- "reason": (detail.reason as Any?) ?? NSNull()
+ "value": (detail.value as Any),
+ "variationIndex": (detail.variationIndex as Any),
+ "reason": (detail.reason as Any)
]
resolve(jsonObject)
}
- @objc func trackNumber(_ eventName: String, data: NSNumber) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data)
+ @objc func trackNumber(_ eventName: String, data: NSNumber, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data)
}
- @objc func trackBool(_ eventName: String, data: ObjCBool) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data.boolValue)
+ @objc func trackBool(_ eventName: String, data: ObjCBool, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data.boolValue)
}
- @objc func trackString(_ eventName: String, data: String) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data)
+ @objc func trackString(_ eventName: String, data: String, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data)
}
- @objc func trackArray(_ eventName: String, data: NSArray) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data)
+ @objc func trackArray(_ eventName: String, data: NSArray, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data)
}
- @objc func trackObject(_ eventName: String, data: NSDictionary) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data.swiftDictionary)
+ @objc func trackObject(_ eventName: String, data: NSDictionary, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data.swiftDictionary)
}
- @objc func track(_ eventName: String) -> Void {
- try? LDClient.get()!.track(key: eventName)
+ @objc func track(_ eventName: String, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName)
}
- @objc func trackNumberMetricValue(_ eventName: String, data: NSNumber, metricValue: NSNumber) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data, metricValue: Double(truncating: metricValue))
+ @objc func trackNumberMetricValue(_ eventName: String, data: NSNumber, metricValue: NSNumber, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data, metricValue: Double(truncating: metricValue))
}
- @objc func trackBoolMetricValue(_ eventName: String, data: ObjCBool, metricValue: NSNumber) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data.boolValue, metricValue: Double(truncating: metricValue))
+ @objc func trackBoolMetricValue(_ eventName: String, data: ObjCBool, metricValue: NSNumber, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data.boolValue, metricValue: Double(truncating: metricValue))
}
- @objc func trackStringMetricValue(_ eventName: String, data: String, metricValue: NSNumber) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data, metricValue: Double(truncating: metricValue))
+ @objc func trackStringMetricValue(_ eventName: String, data: String, metricValue: NSNumber, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data, metricValue: Double(truncating: metricValue))
}
- @objc func trackArrayMetricValue(_ eventName: String, data: NSArray, metricValue: NSNumber) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data, metricValue: Double(truncating: metricValue))
+ @objc func trackArrayMetricValue(_ eventName: String, data: NSArray, metricValue: NSNumber, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data, metricValue: Double(truncating: metricValue))
}
- @objc func trackObjectMetricValue(_ eventName: String, data: NSDictionary, metricValue: NSNumber) -> Void {
- try? LDClient.get()!.track(key: eventName, data: data.swiftDictionary, metricValue: Double(truncating: metricValue))
+ @objc func trackObjectMetricValue(_ eventName: String, data: NSDictionary, metricValue: NSNumber, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, data: data.swiftDictionary, metricValue: Double(truncating: metricValue))
}
- @objc func trackMetricValue(_ eventName: String, metricValue: NSNumber) -> Void {
- try? LDClient.get()!.track(key: eventName, metricValue: Double(truncating: metricValue))
+ @objc func trackMetricValue(_ eventName: String, metricValue: NSNumber, environment: String) -> Void {
+ try? LDClient.get(environment: environment)!.track(key: eventName, metricValue: Double(truncating: metricValue))
}
@objc func setOffline(_ resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
@@ -446,7 +455,7 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
}
@objc func isOffline(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(!LDClient.get()!.isOnline)
+ resolve(LDClient.get()!.isOnline)
}
@objc func setOnline(_ resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
@@ -475,9 +484,9 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
}
}
- @objc func allFlags(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ @objc func allFlags(_ environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var allFlagsDict: [String: Any] = [:]
- if let allFlags = LDClient.get()!.allFlags {
+ if let allFlags = LDClient.get(environment: environment)!.allFlags {
for (key, value) in allFlags {
allFlagsDict[key] = value
}
@@ -485,36 +494,8 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
resolve(allFlagsDict as NSDictionary)
}
- @objc func registerFeatureFlagListener(_ flagKey: String) -> Void {
- let flagChangeOwner = flagKey as LDObserverOwner
- if listenerKeys[flagKey] == nil {
- listenerKeys[flagKey] = flagChangeOwner
- } else {
- return
- }
- LDClient.get()!.observe(keys: [flagKey], owner: flagChangeOwner, handler: { (changedFlags) in
- if changedFlags[flagKey] != nil && self.bridge != nil {
- self.sendEvent(withName: self.FLAG_PREFIX, body: ["flagKey": flagKey])
- }
- })
- }
-
- private func unregisterListener(_ key: String) -> Void {
- let owner = key as LDObserverOwner
- if listenerKeys[key] != nil {
- listenerKeys.removeValue(forKey: key)
- } else {
- return
- }
- LDClient.get()!.stopObserving(owner: owner)
- }
-
- @objc func unregisterFeatureFlagListener(_ flagKey: String) -> Void {
- unregisterListener(flagKey)
- }
-
- @objc func getConnectionMode(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let connectionInformation = LDClient.get()!.getConnectionInformation()
+ @objc func getConnectionMode(_ environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let connectionInformation = LDClient.get(environment: environment)!.getConnectionInformation()
var connectionMode: String
switch connectionInformation.currentConnectionMode {
case .streaming:
@@ -530,16 +511,16 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
}
// lastKnownFlagValidity is nil if either no connection has ever been successfully made or if the SDK has an active streaming connection. It will have a value if 1) in polling mode and at least one poll has completed successfully, or 2) if in streaming mode whenever the streaming connection closes.
- @objc func getLastSuccessfulConnection(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.getConnectionInformation().lastKnownFlagValidity ?? 0)
+ @objc func getLastSuccessfulConnection(_ environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.getConnectionInformation().lastKnownFlagValidity ?? 0)
}
- @objc func getLastFailedConnection(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- resolve(LDClient.get()!.getConnectionInformation().lastFailedConnection ?? 0)
+ @objc func getLastFailedConnection(_ environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ resolve(LDClient.get(environment: environment)!.getConnectionInformation().lastFailedConnection ?? 0)
}
- @objc func getLastFailure(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
- let connectionInformation = LDClient.get()!.getConnectionInformation()
+ @objc func getLastFailure(_ environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ let connectionInformation = LDClient.get(environment: environment)!.getConnectionInformation()
var failureReason: String
switch connectionInformation.lastConnectionFailureReason {
case .unauthorized:
@@ -553,48 +534,80 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
}
resolve(failureReason)
}
+
+ private func envConcat(environment: String, identifier: String) -> String {
+ return environment + ";" + identifier
+ }
+
+ @objc func registerFeatureFlagListener(_ flagKey: String, environment: String) -> Void {
+ let flagChangeOwner = flagKey as LDObserverOwner
+ if listenerKeys[flagKey] == nil {
+ listenerKeys[flagKey] = flagChangeOwner
+ } else {
+ return
+ }
+ LDClient.get(environment: environment)!.observe(keys: [flagKey], owner: flagChangeOwner, handler: { (changedFlags) in
+ if changedFlags[flagKey] != nil && self.bridge != nil {
+ self.sendEvent(withName: self.FLAG_PREFIX, body: ["flagKey": self.envConcat(environment: environment, identifier: flagKey)])
+ }
+ })
+ }
+
+ private func unregisterListener(_ key: String, _ environment: String) -> Void {
+ let owner = key as LDObserverOwner
+ if listenerKeys[key] != nil {
+ listenerKeys.removeValue(forKey: key)
+ } else {
+ return
+ }
+ LDClient.get(environment: environment)!.stopObserving(owner: owner)
+ }
+
+ @objc func unregisterFeatureFlagListener(_ flagKey: String, environment: String) -> Void {
+ unregisterListener(flagKey, environment)
+ }
- @objc func registerCurrentConnectionModeListener(_ listenerId: String) -> Void {
+ @objc func registerCurrentConnectionModeListener(_ listenerId: String, environment: String) -> Void {
let currentConnectionModeOwner = listenerId as LDObserverOwner
if listenerKeys[listenerId] == nil {
listenerKeys.removeValue(forKey: listenerId)
} else {
return
}
- LDClient.get()!.observeCurrentConnectionMode(owner: currentConnectionModeOwner, handler: { (connectionMode) in
+ LDClient.get(environment: environment)!.observeCurrentConnectionMode(owner: currentConnectionModeOwner, handler: { (connectionMode) in
if self.bridge != nil {
- self.sendEvent(withName: self.CONNECTION_MODE_PREFIX, body: ["connectionMode": connectionMode])
+ self.sendEvent(withName: self.CONNECTION_MODE_PREFIX, body: ["connectionMode": connectionMode, "listenerId": self.envConcat(environment: environment, identifier: listenerId)])
}
})
}
- @objc func unregisterCurrentConnectionModeListener(_ listenerId: String) -> Void {
- unregisterListener(listenerId)
+ @objc func unregisterCurrentConnectionModeListener(_ listenerId: String, environment: String) -> Void {
+ unregisterListener(listenerId, environment)
}
- @objc func registerAllFlagsListener(_ listenerId: String) -> Void {
+ @objc func registerAllFlagsListener(_ listenerId: String, environment: String) -> Void {
let flagChangeOwner = listenerId as LDObserverOwner
if listenerKeys[listenerId] == nil {
listenerKeys[listenerId] = flagChangeOwner
} else {
return
}
- LDClient.get()!.observeAll(owner: flagChangeOwner, handler: { (changedFlags) in
+ LDClient.get(environment: environment)!.observeAll(owner: flagChangeOwner, handler: { (changedFlags) in
if self.bridge != nil {
- self.sendEvent(withName: self.ALL_FLAGS_PREFIX, body: ["flagKeys": changedFlags.keys.description])
+ self.sendEvent(withName: self.ALL_FLAGS_PREFIX, body: ["flagKeys": changedFlags.keys.description, "listenerId": self.envConcat(environment: environment, identifier: listenerId)])
}
})
}
- @objc func unregisterAllFlagsListener(_ listenerId: String) -> Void {
- unregisterListener(listenerId)
+ @objc func unregisterAllFlagsListener(_ listenerId: String, environment: String) -> Void {
+ unregisterListener(listenerId, environment)
}
- @objc func isInitialized(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
+ @objc func isInitialized(_ environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
if LDClient.get() == nil {
resolve(false)
} else {
- resolve(LDClient.get()!.isInitialized)
+ resolve(LDClient.get(environment: environment)!.isInitialized)
}
}
}
diff --git a/ios/LaunchdarklyReactNativeClientBridge.m b/ios/LaunchdarklyReactNativeClientBridge.m
index af3931a..76bf0c3 100644
--- a/ios/LaunchdarklyReactNativeClientBridge.m
+++ b/ios/LaunchdarklyReactNativeClientBridge.m
@@ -7,85 +7,85 @@ @interface RCT_EXTERN_MODULE(LaunchdarklyReactNativeClient, RCTEventEmitter)
RCT_EXTERN_METHOD(configureWithTimeout:(NSDictionary *)config userConfig:(NSDictionary *)userConfig timeout:(NSInteger *)timeout resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(boolVariationDefaultValue:(NSString *)flagKey defaultValue:(BOOL *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(boolVariationDefaultValue:(NSString *)flagKey defaultValue:(BOOL *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(intVariationDefaultValue:(NSString *)flagKey defaultValue:(NSInteger *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(intVariationDefaultValue:(NSString *)flagKey defaultValue:(NSInteger *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(floatVariationDefaultValue:(NSString *)flagKey defaultValue:(CGFloat *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(floatVariationDefaultValue:(NSString *)flagKey defaultValue:(CGFloat *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(stringVariationDefaultValue:(NSString *)flagKey defaultValue:(NSString *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(stringVariationDefaultValue:(NSString *)flagKey defaultValue:(NSString *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(boolVariation:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(boolVariation:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(intVariation:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(intVariation:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(floatVariation:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(floatVariation:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(stringVariation:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(stringVariation:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationNone:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationNone:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationNumber:(NSString *)flagKey defaultValue:(NSNumber *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationNumber:(NSString *)flagKey defaultValue:(NSNumber *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationBool:(NSString *)flagKey defaultValue:(BOOL *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationBool:(NSString *)flagKey defaultValue:(BOOL *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationString:(NSString *)flagKey defaultValue:(NSString *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationString:(NSString *)flagKey defaultValue:(NSString *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationArray:(NSString *)flagKey defaultValue:(NSArray *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationArray:(NSString *)flagKey defaultValue:(NSArray *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationObject:(NSString *)flagKey defaultValue:(NSDictionary *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationObject:(NSString *)flagKey defaultValue:(NSDictionary *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(boolVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(BOOL *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(boolVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(BOOL *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(intVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(NSInteger *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(intVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(NSInteger *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(floatVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(CGFloat *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(floatVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(CGFloat *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(stringVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(NSString *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(stringVariationDetailDefaultValue:(NSString *)flagKey defaultValue:(NSString *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(boolVariationDetail:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(boolVariationDetail:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(intVariationDetail:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(intVariationDetail:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(floatVariationDetail:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(floatVariationDetail:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(stringVariationDetail:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(stringVariationDetail:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationDetailNone:(NSString *)flagKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationDetailNone:(NSString *)flagKey environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationDetailNumber:(NSString *)flagKey defaultValue:(NSNumber *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationDetailNumber:(NSString *)flagKey defaultValue:(NSNumber *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationDetailBool:(NSString *)flagKey defaultValue:(BOOL *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationDetailBool:(NSString *)flagKey defaultValue:(BOOL *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationDetailString:(NSString *)flagKey defaultValue:(NSString *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationDetailString:(NSString *)flagKey defaultValue:(NSString *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationDetailArray:(NSString *)flagKey defaultValue:(NSArray *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationDetailArray:(NSString *)flagKey defaultValue:(NSArray *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(jsonVariationDetailObject:(NSString *)flagKey defaultValue:(NSDictionary *)defaultValue resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(jsonVariationDetailObject:(NSString *)flagKey defaultValue:(NSDictionary *)defaultValue environment:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(trackBool:(NSString *)eventName data:(BOOL *)data)
+RCT_EXTERN_METHOD(trackBool:(NSString *)eventName data:(BOOL *)data environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackArray:(NSString *)eventName data:(NSArray *)data)
+RCT_EXTERN_METHOD(trackArray:(NSString *)eventName data:(NSArray *)data environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackNumber:(NSString *)eventName data:(NSNumber * _Nonnull)data)
+RCT_EXTERN_METHOD(trackNumber:(NSString *)eventName data:(NSNumber * _Nonnull)data environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackString:(NSString *)eventName data:(NSString *)data)
+RCT_EXTERN_METHOD(trackString:(NSString *)eventName data:(NSString *)data environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackObject:(NSString *)eventName data:(NSDictionary *)data)
+RCT_EXTERN_METHOD(trackObject:(NSString *)eventName data:(NSDictionary *)data environment:(NSString *)environment)
-RCT_EXTERN_METHOD(track:(NSString *)eventName)
+RCT_EXTERN_METHOD(track:(NSString *)eventName environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackBoolMetricValue:(NSString *)eventName data:(BOOL *)data metricValue:(NSNumber * _Nonnull)metricValue)
+RCT_EXTERN_METHOD(trackBoolMetricValue:(NSString *)eventName data:(BOOL *)data metricValue:(NSNumber * _Nonnull)metricValue environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackArrayMetricValue:(NSString *)eventName data:(NSArray *)data metricValue:(NSNumber * _Nonnull)metricValue)
+RCT_EXTERN_METHOD(trackArrayMetricValue:(NSString *)eventName data:(NSArray *)data metricValue:(NSNumber * _Nonnull)metricValue environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackNumberMetricValue:(NSString *)eventName data:(NSNumber * _Nonnull)data metricValue:(NSNumber * _Nonnull)metricValue)
+RCT_EXTERN_METHOD(trackNumberMetricValue:(NSString *)eventName data:(NSNumber *)data metricValue:(NSNumber * _Nonnull)metricValue environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackStringMetricValue:(NSString *)eventName data:(NSString *)data metricValue:(NSNumber * _Nonnull)metricValue)
+RCT_EXTERN_METHOD(trackStringMetricValue:(NSString *)eventName data:(NSString *)data metricValue:(NSNumber * _Nonnull)metricValue environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackObjectMetricValue:(NSString *)eventName data:(NSDictionary *)data metricValue:(NSNumber * _Nonnull)metricValue)
+RCT_EXTERN_METHOD(trackObjectMetricValue:(NSString *)eventName data:(NSDictionary *)data metricValue:(NSNumber * _Nonnull)metricValue environment:(NSString *)environment)
-RCT_EXTERN_METHOD(trackMetricValue:(NSString *)eventName metricValue:(NSNumber * _Nonnull)metricValue)
+RCT_EXTERN_METHOD(trackMetricValue:(NSString *)eventName metricValue:(NSNumber * _Nonnull)metricValue environment:(NSString *)environment)
RCT_EXTERN_METHOD(setOffline:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
@@ -99,28 +99,28 @@ @interface RCT_EXTERN_MODULE(LaunchdarklyReactNativeClient, RCTEventEmitter)
RCT_EXTERN_METHOD(identify:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(allFlags:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(allFlags:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(registerFeatureFlagListener:(NSString *)flagKey)
+RCT_EXTERN_METHOD(registerFeatureFlagListener:(NSString *)flagKey environment:(NSString *)environment)
-RCT_EXTERN_METHOD(unregisterFeatureFlagListener:(NSString *)flagKey)
+RCT_EXTERN_METHOD(unregisterFeatureFlagListener:(NSString *)flagKey environment:(NSString *)environment)
-RCT_EXTERN_METHOD(registerCurrentConnectionModeListener:(NSString *)listenerId)
+RCT_EXTERN_METHOD(registerCurrentConnectionModeListener:(NSString *)listenerId environment:(NSString *)environment)
-RCT_EXTERN_METHOD(unregisterCurrentConnectionModeListener:(NSString *)listenerId)
+RCT_EXTERN_METHOD(unregisterCurrentConnectionModeListener:(NSString *)listenerId environment:(NSString *)environment)
-RCT_EXTERN_METHOD(registerAllFlagsListener:(NSString *)listenerId)
+RCT_EXTERN_METHOD(registerAllFlagsListener:(NSString *)listenerId environment:(NSString *)environment)
-RCT_EXTERN_METHOD(unregisterAllFlagsListener:(NSString *)listenerId)
+RCT_EXTERN_METHOD(unregisterAllFlagsListener:(NSString *)listenerId environment:(NSString *)environment)
-RCT_EXTERN_METHOD(isInitialized:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(isInitialized:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(getConnectionMode:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(getConnectionMode:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(getLastSuccessfulConnection:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(getLastSuccessfulConnection:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(getLastFailedConnection:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(getLastFailedConnection:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
-RCT_EXTERN_METHOD(getLastFailure:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
+RCT_EXTERN_METHOD(getLastFailure:(NSString *)environment resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
@end
diff --git a/test-types.ts b/test-types.ts
index f311656..94b3b69 100644
--- a/test-types.ts
+++ b/test-types.ts
@@ -41,6 +41,7 @@ async function tests() {
offline: true,
debugMode: true,
evaluationReasons: true,
+ secondaryMobileKeys: {'test' : 'fake_key'},
maxCachedUsers: 6,
diagnosticOptOut: true,
diagnosticRecordingIntervalMillis: 100000,
@@ -49,6 +50,7 @@ async function tests() {
const userWithKeyOnly: LDUser = { key: 'user' };
const user: LDUser = {
key: 'user',
+ secondary: 'user.secondary',
name: 'name',
firstName: 'first',
lastName: 'last',
@@ -64,7 +66,7 @@ async function tests() {
const timeoutClient: LDClient = new LDClient();
const configure: null = await client.configure(configWithAllOptions, user);
- const configureWithTimeout: null = await timeoutClient.configure(configWithAllOptions, user, 10);
+ const configureWithTimeout: null = await timeoutClient.configure(configWithAllOptions, userWithKeyOnly, 10);
const identify: null = await client.identify(user);
const boolFlagValue: boolean = await client.boolVariation('key', false);
@@ -79,6 +81,12 @@ async function tests() {
const stringDetail: LDEvaluationDetail = await client.stringVariationDetail('key', 'default');
const jsonDetail: LDEvaluationDetail> = await client.jsonVariationDetail('key', jsonObj);
+ const boolDetailMulti: LDEvaluationDetail = await client.boolVariationDetail('key', false, 'test');
+ const intDetailMulti: LDEvaluationDetail = await client.intVariationDetail('key', 2, 'test');
+ const floatDetailMulti: LDEvaluationDetail = await client.floatVariationDetail('key', 2.3, 'test');
+ const stringDetailMulti: LDEvaluationDetail = await client.stringVariationDetail('key', 'default', 'test');
+ const jsonDetailMulti: LDEvaluationDetail> = await client.jsonVariationDetail('key', jsonObj, 'test');
+
const detailIndex: number | undefined = boolDetail.variationIndex;
const detailReason: LDEvaluationReason = boolDetail.reason;
const detailBoolValue: boolean = boolDetail.value;