configcat-common
Version:
ConfigCat is a configuration as a service that lets you manage your features and configurations without actually deploying new code.
673 lines (672 loc) • 36.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SettingKeyValue = exports.ConfigCatClient = exports.ConfigCatClientCache = void 0;
var tslib_1 = require("tslib");
var AutoPollConfigService_1 = require("./AutoPollConfigService");
var ConfigCatClientOptions_1 = require("./ConfigCatClientOptions");
var ConfigServiceBase_1 = require("./ConfigServiceBase");
var FlagOverrides_1 = require("./FlagOverrides");
var LazyLoadConfigService_1 = require("./LazyLoadConfigService");
var ManualPollConfigService_1 = require("./ManualPollConfigService");
var Polyfills_1 = require("./Polyfills");
var RolloutEvaluator_1 = require("./RolloutEvaluator");
var Utils_1 = require("./Utils");
var ConfigCatClientCache = /** @class */ (function () {
function ConfigCatClientCache() {
this.instances = {};
}
ConfigCatClientCache.prototype.getOrCreate = function (options, configCatKernel) {
var instance;
var cachedInstance = this.instances[options.sdkKey];
if (cachedInstance) {
var weakRef = cachedInstance[0];
instance = weakRef.deref();
if (instance) {
return [instance, true];
}
}
var token = {};
instance = new ConfigCatClient(options, configCatKernel, token);
var weakRefCtor = Polyfills_1.isWeakRefAvailable() ? WeakRef : Polyfills_1.getWeakRefStub();
this.instances[options.sdkKey] = [new weakRefCtor(instance), token];
return [instance, false];
};
ConfigCatClientCache.prototype.remove = function (sdkKey, cacheToken) {
var cachedInstance = this.instances[sdkKey];
if (cachedInstance) {
var weakRef = cachedInstance[0], token = cachedInstance[1];
var instanceIsAvailable = !!weakRef.deref();
if (!instanceIsAvailable || token === cacheToken) {
delete this.instances[sdkKey];
return instanceIsAvailable;
}
}
return false;
};
ConfigCatClientCache.prototype.clear = function () {
var removedInstances = [];
for (var _i = 0, _a = Object.entries(this.instances); _i < _a.length; _i++) {
var _b = _a[_i], sdkKey = _b[0], weakRef = _b[1][0];
var instance = weakRef.deref();
if (instance) {
removedInstances.push(instance);
}
delete this.instances[sdkKey];
}
return removedInstances;
};
return ConfigCatClientCache;
}());
exports.ConfigCatClientCache = ConfigCatClientCache;
var clientInstanceCache = new ConfigCatClientCache();
var ConfigCatClient = /** @class */ (function () {
function ConfigCatClient(options, configCatKernel, cacheToken) {
var _a;
this.cacheToken = cacheToken;
/** @inheritdoc */
this.addListener = this.on;
/** @inheritdoc */
this.off = this.removeListener;
if (!options) {
throw new Error("Invalid 'options' value");
}
this.options = options;
this.options.logger.debug("Initializing ConfigCatClient. Options: " + JSON.stringify(this.options));
if (!configCatKernel) {
throw new Error("Invalid 'configCatKernel' value");
}
if (!configCatKernel.configFetcher) {
throw new Error("Invalid 'configCatKernel.configFetcher' value");
}
// To avoid possible memory leaks, the components of the client should not hold a strong reference to the hooks object (see also SafeHooksWrapper).
this.hooks = options.yieldHooks();
if (options.defaultUser) {
this.setDefaultUser(options.defaultUser);
}
this.evaluator = new RolloutEvaluator_1.RolloutEvaluator(options.logger);
if (((_a = options.flagOverrides) === null || _a === void 0 ? void 0 : _a.behaviour) !== FlagOverrides_1.OverrideBehaviour.LocalOnly) {
this.configService =
options instanceof ConfigCatClientOptions_1.AutoPollOptions ? new AutoPollConfigService_1.AutoPollConfigService(configCatKernel.configFetcher, options) :
options instanceof ConfigCatClientOptions_1.ManualPollOptions ? new ManualPollConfigService_1.ManualPollConfigService(configCatKernel.configFetcher, options) :
options instanceof ConfigCatClientOptions_1.LazyLoadOptions ? new LazyLoadConfigService_1.LazyLoadConfigService(configCatKernel.configFetcher, options) :
Utils_1.throwError(new Error("Invalid 'options' value"));
}
else {
this.hooks.emit("clientReady", ConfigServiceBase_1.ClientCacheState.HasLocalOverrideFlagDataOnly);
}
this.suppressFinalize = registerForFinalization(this, { sdkKey: options.sdkKey, cacheToken: cacheToken, configService: this.configService, logger: options.logger });
}
Object.defineProperty(ConfigCatClient, "instanceCache", {
get: function () { return clientInstanceCache; },
enumerable: false,
configurable: true
});
ConfigCatClient.get = function (sdkKey, pollingMode, options, configCatKernel) {
var _a;
var invalidSdkKeyError = "Invalid 'sdkKey' value";
if (!sdkKey) {
throw new Error(invalidSdkKeyError);
}
var optionsClass = pollingMode === ConfigCatClientOptions_1.PollingMode.AutoPoll ? ConfigCatClientOptions_1.AutoPollOptions :
pollingMode === ConfigCatClientOptions_1.PollingMode.ManualPoll ? ConfigCatClientOptions_1.ManualPollOptions :
pollingMode === ConfigCatClientOptions_1.PollingMode.LazyLoad ? ConfigCatClientOptions_1.LazyLoadOptions :
Utils_1.throwError(new Error("Invalid 'pollingMode' value"));
var actualOptions = new optionsClass(sdkKey, configCatKernel.sdkType, configCatKernel.sdkVersion, options, configCatKernel.defaultCacheFactory, configCatKernel.eventEmitterFactory);
if (((_a = actualOptions.flagOverrides) === null || _a === void 0 ? void 0 : _a.behaviour) !== FlagOverrides_1.OverrideBehaviour.LocalOnly && !isValidSdkKey(sdkKey, actualOptions.baseUrlOverriden)) {
throw new Error(invalidSdkKeyError);
}
var _b = clientInstanceCache.getOrCreate(actualOptions, configCatKernel), instance = _b[0], instanceAlreadyCreated = _b[1];
if (instanceAlreadyCreated && options) {
actualOptions.logger.clientIsAlreadyCreated(sdkKey);
}
return instance;
};
ConfigCatClient.finalize = function (data) {
// Safeguard against situations where user forgets to dispose of the client instance.
var _a;
(_a = data.logger) === null || _a === void 0 ? void 0 : _a.debug("finalize() called");
if (data.cacheToken) {
clientInstanceCache.remove(data.sdkKey, data.cacheToken);
}
ConfigCatClient.close(data.configService, data.logger);
};
ConfigCatClient.close = function (configService, logger, hooks) {
logger === null || logger === void 0 ? void 0 : logger.debug("close() called");
hooks === null || hooks === void 0 ? void 0 : hooks.tryDisconnect();
configService === null || configService === void 0 ? void 0 : configService.dispose();
};
ConfigCatClient.prototype.dispose = function () {
var options = this.options;
options.logger.debug("dispose() called");
if (this.cacheToken) {
clientInstanceCache.remove(options.sdkKey, this.cacheToken);
}
ConfigCatClient.close(this.configService, options.logger, this.hooks);
this.suppressFinalize();
};
ConfigCatClient.disposeAll = function () {
var removedInstances = clientInstanceCache.clear();
var errors;
for (var _i = 0, removedInstances_1 = removedInstances; _i < removedInstances_1.length; _i++) {
var instance = removedInstances_1[_i];
try {
ConfigCatClient.close(instance.configService, instance.options.logger, instance.hooks);
instance.suppressFinalize();
}
catch (err) {
errors !== null && errors !== void 0 ? errors : (errors = []);
errors.push(err);
}
}
if (errors) {
throw typeof AggregateError !== "undefined" ? new AggregateError(errors) : errors.pop();
}
};
ConfigCatClient.prototype.getValueAsync = function (key, defaultValue, user) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var value, evaluationDetails, remoteConfig, settings, err_1;
var _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
this.options.logger.debug("getValueAsync() called.");
validateKey(key);
ensureAllowedDefaultValue(defaultValue);
remoteConfig = null;
user !== null && user !== void 0 ? user : (user = this.defaultUser);
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
settings = void 0;
return [4 /*yield*/, this.getSettingsAsync()];
case 2:
_a = _b.sent(), settings = _a[0], remoteConfig = _a[1];
evaluationDetails = RolloutEvaluator_1.evaluate(this.evaluator, settings, key, defaultValue, user, remoteConfig, this.options.logger);
value = evaluationDetails.value;
return [3 /*break*/, 4];
case 3:
err_1 = _b.sent();
this.options.logger.settingEvaluationErrorSingle("getValueAsync", key, "defaultValue", defaultValue, err_1);
evaluationDetails = RolloutEvaluator_1.evaluationDetailsFromDefaultValue(key, defaultValue, RolloutEvaluator_1.getTimestampAsDate(remoteConfig), user, Utils_1.errorToString(err_1), err_1);
value = defaultValue;
return [3 /*break*/, 4];
case 4:
this.hooks.emit("flagEvaluated", evaluationDetails);
return [2 /*return*/, value];
}
});
});
};
ConfigCatClient.prototype.getValueDetailsAsync = function (key, defaultValue, user) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var evaluationDetails, remoteConfig, settings, err_2;
var _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
this.options.logger.debug("getValueDetailsAsync() called.");
validateKey(key);
ensureAllowedDefaultValue(defaultValue);
remoteConfig = null;
user !== null && user !== void 0 ? user : (user = this.defaultUser);
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
settings = void 0;
return [4 /*yield*/, this.getSettingsAsync()];
case 2:
_a = _b.sent(), settings = _a[0], remoteConfig = _a[1];
evaluationDetails = RolloutEvaluator_1.evaluate(this.evaluator, settings, key, defaultValue, user, remoteConfig, this.options.logger);
return [3 /*break*/, 4];
case 3:
err_2 = _b.sent();
this.options.logger.settingEvaluationErrorSingle("getValueDetailsAsync", key, "defaultValue", defaultValue, err_2);
evaluationDetails = RolloutEvaluator_1.evaluationDetailsFromDefaultValue(key, defaultValue, RolloutEvaluator_1.getTimestampAsDate(remoteConfig), user, Utils_1.errorToString(err_2), err_2);
return [3 /*break*/, 4];
case 4:
this.hooks.emit("flagEvaluated", evaluationDetails);
return [2 /*return*/, evaluationDetails];
}
});
});
};
ConfigCatClient.prototype.getAllKeysAsync = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var defaultReturnValue, settings, err_3;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.options.logger.debug("getAllKeysAsync() called.");
defaultReturnValue = "empty array";
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.getSettingsAsync()];
case 2:
settings = (_a.sent())[0];
if (!RolloutEvaluator_1.checkSettingsAvailable(settings, this.options.logger, defaultReturnValue)) {
return [2 /*return*/, []];
}
return [2 /*return*/, Object.keys(settings)];
case 3:
err_3 = _a.sent();
this.options.logger.settingEvaluationError("getAllKeysAsync", defaultReturnValue, err_3);
return [2 /*return*/, []];
case 4: return [2 /*return*/];
}
});
});
};
ConfigCatClient.prototype.getAllValuesAsync = function (user) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var defaultReturnValue, result, evaluationDetailsArray, evaluationErrors, _a, settings, remoteConfig, err_4, _i, evaluationDetailsArray_1, evaluationDetail;
var _b;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
this.options.logger.debug("getAllValuesAsync() called.");
defaultReturnValue = "empty array";
user !== null && user !== void 0 ? user : (user = this.defaultUser);
_c.label = 1;
case 1:
_c.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.getSettingsAsync()];
case 2:
_a = _c.sent(), settings = _a[0], remoteConfig = _a[1];
_b = RolloutEvaluator_1.evaluateAll(this.evaluator, settings, user, remoteConfig, this.options.logger, defaultReturnValue), evaluationDetailsArray = _b[0], evaluationErrors = _b[1];
result = evaluationDetailsArray.map(function (details) { return new SettingKeyValue(details.key, details.value); });
return [3 /*break*/, 4];
case 3:
err_4 = _c.sent();
this.options.logger.settingEvaluationError("getAllValuesAsync", defaultReturnValue, err_4);
return [2 /*return*/, []];
case 4:
if (evaluationErrors === null || evaluationErrors === void 0 ? void 0 : evaluationErrors.length) {
this.options.logger.settingEvaluationError("getAllValuesAsync", "evaluation result", typeof AggregateError !== "undefined" ? new AggregateError(evaluationErrors) : evaluationErrors.pop());
}
for (_i = 0, evaluationDetailsArray_1 = evaluationDetailsArray; _i < evaluationDetailsArray_1.length; _i++) {
evaluationDetail = evaluationDetailsArray_1[_i];
this.hooks.emit("flagEvaluated", evaluationDetail);
}
return [2 /*return*/, result];
}
});
});
};
ConfigCatClient.prototype.getAllValueDetailsAsync = function (user) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var defaultReturnValue, evaluationDetailsArray, evaluationErrors, _a, settings, remoteConfig, err_5, _i, evaluationDetailsArray_2, evaluationDetail;
var _b;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
this.options.logger.debug("getAllValueDetailsAsync() called.");
defaultReturnValue = "empty array";
user !== null && user !== void 0 ? user : (user = this.defaultUser);
_c.label = 1;
case 1:
_c.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.getSettingsAsync()];
case 2:
_a = _c.sent(), settings = _a[0], remoteConfig = _a[1];
_b = RolloutEvaluator_1.evaluateAll(this.evaluator, settings, user, remoteConfig, this.options.logger, defaultReturnValue), evaluationDetailsArray = _b[0], evaluationErrors = _b[1];
return [3 /*break*/, 4];
case 3:
err_5 = _c.sent();
this.options.logger.settingEvaluationError("getAllValueDetailsAsync", defaultReturnValue, err_5);
return [2 /*return*/, []];
case 4:
if (evaluationErrors === null || evaluationErrors === void 0 ? void 0 : evaluationErrors.length) {
this.options.logger.settingEvaluationError("getAllValueDetailsAsync", "evaluation result", typeof AggregateError !== "undefined" ? new AggregateError(evaluationErrors) : evaluationErrors.pop());
}
for (_i = 0, evaluationDetailsArray_2 = evaluationDetailsArray; _i < evaluationDetailsArray_2.length; _i++) {
evaluationDetail = evaluationDetailsArray_2[_i];
this.hooks.emit("flagEvaluated", evaluationDetail);
}
return [2 /*return*/, evaluationDetailsArray];
}
});
});
};
ConfigCatClient.prototype.getKeyAndValueAsync = function (variationId) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var defaultReturnValue, settings, _i, _a, _b, settingKey, setting, targetingRules, i, then, j, percentageOption, percentageOptions, i, percentageOption, err_6;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
this.options.logger.debug("getKeyAndValueAsync() called.");
defaultReturnValue = "null";
_c.label = 1;
case 1:
_c.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.getSettingsAsync()];
case 2:
settings = (_c.sent())[0];
if (!RolloutEvaluator_1.checkSettingsAvailable(settings, this.options.logger, defaultReturnValue)) {
return [2 /*return*/, null];
}
for (_i = 0, _a = Object.entries(settings); _i < _a.length; _i++) {
_b = _a[_i], settingKey = _b[0], setting = _b[1];
if (variationId === setting.variationId) {
return [2 /*return*/, new SettingKeyValue(settingKey, ensureAllowedValue(setting.value))];
}
targetingRules = settings[settingKey].targetingRules;
if (targetingRules && targetingRules.length > 0) {
for (i = 0; i < targetingRules.length; i++) {
then = targetingRules[i].then;
if (Utils_1.isArray(then)) {
for (j = 0; j < then.length; j++) {
percentageOption = then[j];
if (variationId === percentageOption.variationId) {
return [2 /*return*/, new SettingKeyValue(settingKey, ensureAllowedValue(percentageOption.value))];
}
}
}
else if (variationId === then.variationId) {
return [2 /*return*/, new SettingKeyValue(settingKey, ensureAllowedValue(then.value))];
}
}
}
percentageOptions = settings[settingKey].percentageOptions;
if (percentageOptions && percentageOptions.length > 0) {
for (i = 0; i < percentageOptions.length; i++) {
percentageOption = percentageOptions[i];
if (variationId === percentageOption.variationId) {
return [2 /*return*/, new SettingKeyValue(settingKey, ensureAllowedValue(percentageOption.value))];
}
}
}
}
this.options.logger.settingForVariationIdIsNotPresent(variationId);
return [3 /*break*/, 4];
case 3:
err_6 = _c.sent();
this.options.logger.settingEvaluationError("getKeyAndValueAsync", defaultReturnValue, err_6);
return [3 /*break*/, 4];
case 4: return [2 /*return*/, null];
}
});
});
};
ConfigCatClient.prototype.forceRefreshAsync = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result, err_7;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.options.logger.debug("forceRefreshAsync() called.");
if (!this.configService) return [3 /*break*/, 5];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.configService.refreshConfigAsync()];
case 2:
result = (_a.sent())[0];
return [2 /*return*/, result];
case 3:
err_7 = _a.sent();
this.options.logger.forceRefreshError("forceRefreshAsync", err_7);
return [2 /*return*/, ConfigServiceBase_1.RefreshResult.failure(Utils_1.errorToString(err_7), err_7)];
case 4: return [3 /*break*/, 6];
case 5: return [2 /*return*/, ConfigServiceBase_1.RefreshResult.failure("Client is configured to use the LocalOnly override behavior, which prevents making HTTP requests.")];
case 6: return [2 /*return*/];
}
});
});
};
ConfigCatClient.prototype.setDefaultUser = function (defaultUser) {
this.defaultUser = defaultUser;
};
ConfigCatClient.prototype.clearDefaultUser = function () {
this.defaultUser = void 0;
};
Object.defineProperty(ConfigCatClient.prototype, "isOffline", {
get: function () {
var _a, _b;
return (_b = (_a = this.configService) === null || _a === void 0 ? void 0 : _a.isOffline) !== null && _b !== void 0 ? _b : true;
},
enumerable: false,
configurable: true
});
ConfigCatClient.prototype.setOnline = function () {
if (this.configService) {
this.configService.setOnline();
}
else {
this.options.logger.configServiceMethodHasNoEffectDueToOverrideBehavior(FlagOverrides_1.OverrideBehaviour[FlagOverrides_1.OverrideBehaviour.LocalOnly], "setOnline");
}
};
ConfigCatClient.prototype.setOffline = function () {
var _a;
(_a = this.configService) === null || _a === void 0 ? void 0 : _a.setOffline();
};
ConfigCatClient.prototype.waitForReady = function () {
var configService = this.configService;
return configService ? configService.readyPromise : Promise.resolve(ConfigServiceBase_1.ClientCacheState.HasLocalOverrideFlagDataOnly);
};
ConfigCatClient.prototype.snapshot = function () {
var _a, _b, _c;
var _this = this;
var _d;
var getRemoteConfig = function () {
var config = _this.options.cache.getInMemory();
var settings = !config.isEmpty ? config.config.settings : null;
return [settings, config];
};
var remoteSettings;
var remoteConfig;
var flagOverrides = (_d = this.options) === null || _d === void 0 ? void 0 : _d.flagOverrides;
if (flagOverrides) {
var localSettings = flagOverrides.dataSource.getOverridesSync();
switch (flagOverrides.behaviour) {
case FlagOverrides_1.OverrideBehaviour.LocalOnly:
return new Snapshot(localSettings, null, this);
case FlagOverrides_1.OverrideBehaviour.LocalOverRemote:
_a = getRemoteConfig(), remoteSettings = _a[0], remoteConfig = _a[1];
return new Snapshot(tslib_1.__assign(tslib_1.__assign({}, (remoteSettings !== null && remoteSettings !== void 0 ? remoteSettings : {})), localSettings), remoteConfig, this);
case FlagOverrides_1.OverrideBehaviour.RemoteOverLocal:
_b = getRemoteConfig(), remoteSettings = _b[0], remoteConfig = _b[1];
return new Snapshot(tslib_1.__assign(tslib_1.__assign({}, localSettings), (remoteSettings !== null && remoteSettings !== void 0 ? remoteSettings : {})), remoteConfig, this);
}
}
_c = getRemoteConfig(), remoteSettings = _c[0], remoteConfig = _c[1];
return new Snapshot(remoteSettings, remoteConfig, this);
};
ConfigCatClient.prototype.getSettingsAsync = function () {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function () {
var getRemoteConfigAsync, flagOverrides, remoteSettings, remoteConfig, localSettings, _b;
var _c, _d;
var _this = this;
return tslib_1.__generator(this, function (_e) {
switch (_e.label) {
case 0:
this.options.logger.debug("getSettingsAsync() called.");
getRemoteConfigAsync = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var config, settings;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.configService.getConfig()];
case 1:
config = _a.sent();
settings = !config.isEmpty ? config.config.settings : null;
return [2 /*return*/, [settings, config]];
}
});
}); };
flagOverrides = (_a = this.options) === null || _a === void 0 ? void 0 : _a.flagOverrides;
if (!flagOverrides) return [3 /*break*/, 7];
remoteSettings = void 0;
remoteConfig = void 0;
return [4 /*yield*/, flagOverrides.dataSource.getOverrides()];
case 1:
localSettings = _e.sent();
_b = flagOverrides.behaviour;
switch (_b) {
case FlagOverrides_1.OverrideBehaviour.LocalOnly: return [3 /*break*/, 2];
case FlagOverrides_1.OverrideBehaviour.LocalOverRemote: return [3 /*break*/, 3];
case FlagOverrides_1.OverrideBehaviour.RemoteOverLocal: return [3 /*break*/, 5];
}
return [3 /*break*/, 7];
case 2: return [2 /*return*/, [localSettings, null]];
case 3: return [4 /*yield*/, getRemoteConfigAsync()];
case 4:
_c = _e.sent(), remoteSettings = _c[0], remoteConfig = _c[1];
return [2 /*return*/, [tslib_1.__assign(tslib_1.__assign({}, (remoteSettings !== null && remoteSettings !== void 0 ? remoteSettings : {})), localSettings), remoteConfig]];
case 5: return [4 /*yield*/, getRemoteConfigAsync()];
case 6:
_d = _e.sent(), remoteSettings = _d[0], remoteConfig = _d[1];
return [2 /*return*/, [tslib_1.__assign(tslib_1.__assign({}, localSettings), (remoteSettings !== null && remoteSettings !== void 0 ? remoteSettings : {})), remoteConfig]];
case 7: return [4 /*yield*/, getRemoteConfigAsync()];
case 8: return [2 /*return*/, _e.sent()];
}
});
});
};
/** @inheritdoc */
ConfigCatClient.prototype.on = function (eventName, listener) {
this.hooks.on(eventName, listener);
return this;
};
/** @inheritdoc */
ConfigCatClient.prototype.once = function (eventName, listener) {
this.hooks.once(eventName, listener);
return this;
};
/** @inheritdoc */
ConfigCatClient.prototype.removeListener = function (eventName, listener) {
this.hooks.removeListener(eventName, listener);
return this;
};
/** @inheritdoc */
ConfigCatClient.prototype.removeAllListeners = function (eventName) {
this.hooks.removeAllListeners(eventName);
return this;
};
/** @inheritdoc */
ConfigCatClient.prototype.listeners = function (eventName) {
return this.hooks.listeners(eventName);
};
/** @inheritdoc */
ConfigCatClient.prototype.listenerCount = function (eventName) {
return this.hooks.listenerCount(eventName);
};
/** @inheritdoc */
ConfigCatClient.prototype.eventNames = function () {
return this.hooks.eventNames();
};
return ConfigCatClient;
}());
exports.ConfigCatClient = ConfigCatClient;
var Snapshot = /** @class */ (function () {
function Snapshot(mergedSettings, remoteConfig, client) {
this.mergedSettings = mergedSettings;
this.remoteConfig = remoteConfig;
this.defaultUser = client["defaultUser"];
this.evaluator = client["evaluator"];
this.options = client["options"];
this.cacheState = remoteConfig
? client["configService"].getCacheState(remoteConfig)
: ConfigServiceBase_1.ClientCacheState.HasLocalOverrideFlagDataOnly;
}
Object.defineProperty(Snapshot.prototype, "fetchedConfig", {
get: function () {
var config = this.remoteConfig;
return config && !config.isEmpty ? config.config : null;
},
enumerable: false,
configurable: true
});
Snapshot.prototype.getAllKeys = function () { return this.mergedSettings ? Object.keys(this.mergedSettings) : []; };
Snapshot.prototype.getValue = function (key, defaultValue, user) {
this.options.logger.debug("Snapshot.getValue() called.");
validateKey(key);
ensureAllowedDefaultValue(defaultValue);
var value, evaluationDetails;
user !== null && user !== void 0 ? user : (user = this.defaultUser);
try {
evaluationDetails = RolloutEvaluator_1.evaluate(this.evaluator, this.mergedSettings, key, defaultValue, user, this.remoteConfig, this.options.logger);
value = evaluationDetails.value;
}
catch (err) {
this.options.logger.settingEvaluationErrorSingle("Snapshot.getValue", key, "defaultValue", defaultValue, err);
evaluationDetails = RolloutEvaluator_1.evaluationDetailsFromDefaultValue(key, defaultValue, RolloutEvaluator_1.getTimestampAsDate(this.remoteConfig), user, Utils_1.errorToString(err), err);
value = defaultValue;
}
this.options.hooks.emit("flagEvaluated", evaluationDetails);
return value;
};
Snapshot.prototype.getValueDetails = function (key, defaultValue, user) {
this.options.logger.debug("Snapshot.getValueDetails() called.");
validateKey(key);
ensureAllowedDefaultValue(defaultValue);
var evaluationDetails;
user !== null && user !== void 0 ? user : (user = this.defaultUser);
try {
evaluationDetails = RolloutEvaluator_1.evaluate(this.evaluator, this.mergedSettings, key, defaultValue, user, this.remoteConfig, this.options.logger);
}
catch (err) {
this.options.logger.settingEvaluationErrorSingle("Snapshot.getValueDetails", key, "defaultValue", defaultValue, err);
evaluationDetails = RolloutEvaluator_1.evaluationDetailsFromDefaultValue(key, defaultValue, RolloutEvaluator_1.getTimestampAsDate(this.remoteConfig), user, Utils_1.errorToString(err), err);
}
this.options.hooks.emit("flagEvaluated", evaluationDetails);
return evaluationDetails;
};
return Snapshot;
}());
/** Setting key-value pair. */
var SettingKeyValue = /** @class */ (function () {
function SettingKeyValue(settingKey, settingValue) {
this.settingKey = settingKey;
this.settingValue = settingValue;
}
return SettingKeyValue;
}());
exports.SettingKeyValue = SettingKeyValue;
function isValidSdkKey(sdkKey, customBaseUrl) {
var proxyPrefix = "configcat-proxy/";
// NOTE: String.prototype.startsWith was introduced after ES5. We'd rather work around it instead of polyfilling it.
if (customBaseUrl && sdkKey.length > proxyPrefix.length && sdkKey.lastIndexOf(proxyPrefix, 0) === 0) {
return true;
}
var components = sdkKey.split("/");
var keyLength = 22;
switch (components.length) {
case 2: return components[0].length === keyLength && components[1].length === keyLength;
case 3: return components[0] === "configcat-sdk-1" && components[1].length === keyLength && components[2].length === keyLength;
default: return false;
}
}
function validateKey(key) {
if (!key) {
throw new Error("Invalid 'key' value");
}
}
function ensureAllowedDefaultValue(value) {
if (value != null && !RolloutEvaluator_1.isAllowedValue(value)) {
throw new TypeError("The default value must be boolean, number, string, null or undefined.");
}
}
function ensureAllowedValue(value) {
return RolloutEvaluator_1.isAllowedValue(value) ? value : RolloutEvaluator_1.handleInvalidReturnValue(value);
}
var registerForFinalization = function (client, data) {
// Use FinalizationRegistry (finalization callbacks) if the runtime provides that feature.
if (typeof FinalizationRegistry !== "undefined") {
var finalizationRegistry_1 = new FinalizationRegistry(function (data) { return ConfigCatClient["finalize"](data); });
registerForFinalization = function (client, data) {
var unregisterToken = {};
finalizationRegistry_1.register(client, data, unregisterToken);
return function () { return finalizationRegistry_1.unregister(unregisterToken); };
};
}
// If FinalizationRegistry is unavailable, we can't really track finalization.
// (Although we could implement something which resembles finalization callbacks using a weak map + a timer,
// since ConfigCatClientCache also needs to keep (weak) references to the created client instances,
// this hypothetical approach wouldn't work without a complete WeakRef polyfill,
// which is kind of impossible (for more details, see Polyfills.ts).
else {
registerForFinalization = function () { return function () { }; };
}
return registerForFinalization(client, data);
};