UNPKG

statsig-js

Version:

Statsig JavaScript client SDK for single user environments.

989 lines 62.1 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var DynamicConfig_1 = __importDefault(require("./DynamicConfig")); var ErrorBoundary_1 = __importDefault(require("./ErrorBoundary")); var Errors_1 = require("./Errors"); var FeatureGate_1 = __importDefault(require("./FeatureGate")); var Layer_1 = __importDefault(require("./Layer")); var LogEvent_1 = __importDefault(require("./LogEvent")); var StatsigIdentity_1 = __importDefault(require("./StatsigIdentity")); var StatsigLogger_1 = __importDefault(require("./StatsigLogger")); var StatsigNetwork_1 = __importDefault(require("./StatsigNetwork")); var StatsigSDKOptions_1 = __importDefault(require("./StatsigSDKOptions")); var StatsigStore_1 = __importDefault(require("./StatsigStore")); var Diagnostics_1 = __importDefault(require("./utils/Diagnostics")); var EvaluationReason_1 = require("./utils/EvaluationReason"); var Hashing_1 = require("./utils/Hashing"); var OutputLogger_1 = __importDefault(require("./utils/OutputLogger")); var ResponseVerification_1 = require("./utils/ResponseVerification"); var StatsigAsyncStorage_1 = __importDefault(require("./utils/StatsigAsyncStorage")); var StatsigLocalStorage_1 = __importDefault(require("./utils/StatsigLocalStorage")); var Timing_1 = require("./utils/Timing"); var MAX_VALUE_SIZE = 64; var MAX_OBJ_SIZE = 2048; var StatsigClient = /** @class */ (function () { function StatsigClient(sdkKey, user, options) { var _this = this; this.appState = null; this.currentAppState = null; this.appStateChangeSubscription = null; this.onCacheLoadedForReact = null; this.initCalled = false; this.pendingInitPromise = null; this.optionalLoggingSetup = false; this.prefetchedUsersByCacheKey = {}; this.logLayerParameterExposureForLayer = function (layer, parameterName, isManualExposure) { if (isManualExposure === void 0) { isManualExposure = false; } var allocatedExperiment = ''; var exposures = layer._getUndelegatedSecondaryExposures(); var isExplicit = layer._getExplicitParameters().includes(parameterName); if (isExplicit) { allocatedExperiment = layer._getAllocatedExperimentName(); exposures = layer._getSecondaryExposures(); } _this.logger.logLayerExposure(_this.getCurrentUser(), layer.getName(), layer.getRuleID(), exposures, allocatedExperiment, parameterName, isExplicit, layer._getEvaluationDetails(), isManualExposure, _this.store.getBootstrapMetadata()); }; if ((options === null || options === void 0 ? void 0 : options.localMode) !== true && (typeof sdkKey !== 'string' || !sdkKey.startsWith('client-'))) { throw new Errors_1.StatsigInvalidArgumentError('Invalid key provided. You must use a Client SDK Key from the Statsig console to initialize the sdk'); } this.startTime = (0, Timing_1.now)(); this.options = new StatsigSDKOptions_1.default(options); this.logger = new StatsigLogger_1.default(this); Diagnostics_1.default.initialize({ options: this.options, }); this.errorBoundary = new ErrorBoundary_1.default(sdkKey, this.options); this.ready = false; this.sdkKey = sdkKey; OutputLogger_1.default.setLogger(this.options.getOutputLogger()); OutputLogger_1.default.setLogLevel(this.options.getLogLevel()); StatsigLocalStorage_1.default.disabled = this.options.getDisableLocalStorage(); this.identity = new StatsigIdentity_1.default(this.normalizeUser(user !== null && user !== void 0 ? user : null), this.options.getOverrideStableID(), StatsigClient.reactNativeUUID); this.errorBoundary.setStatsigMetadata(this.getStatsigMetadata()); this.network = new StatsigNetwork_1.default(this); this.store = new StatsigStore_1.default(this, this.options.getInitializeValues()); if (this.options.getInitializeValues() != null) { var cb = this.options.getInitCompletionCallback(); this.ready = true; this.initCalled = true; setTimeout(function () { return _this.delayedSetup(); }, 20); this.handleOptionalLogging(); if (cb) { cb((0, Timing_1.now)() - this.startTime, true, null); } } } StatsigClient.prototype.getErrorBoundary = function () { return this.errorBoundary; }; StatsigClient.prototype.getNetwork = function () { return this.network; }; StatsigClient.prototype.getStore = function () { return this.store; }; StatsigClient.prototype.getLogger = function () { return this.logger; }; StatsigClient.prototype.getOptions = function () { return this.options; }; StatsigClient.prototype.getSDKKey = function () { var _this = this; return this.errorBoundary.capture('getSDKKey', function () { var _a; return (_a = _this.sdkKey) !== null && _a !== void 0 ? _a : ''; }, function () { return ''; }); }; StatsigClient.prototype.getCurrentUser = function () { var _this = this; return this.errorBoundary.capture('getCurrentUser', function () { return _this.identity.getUser(); }, function () { return null; }); }; StatsigClient.prototype.getCurrentUserCacheKey = function () { var _this = this; return this.errorBoundary.capture('getCurrentUserCacheKey', function () { return (0, Hashing_1.getUserCacheKey)(_this.getStableID(), _this.getCurrentUser(), _this.getSDKKey()); }, function () { return ({ v1: '', v2: '', v3: '' }); }); }; StatsigClient.prototype.getCurrentUserUnitID = function (idType) { var _this = this; return this.errorBoundary.capture('getCurrentUserUnitID', function () { return _this.getUnitID(_this.getCurrentUser(), idType); }, function () { return ''; }); }; StatsigClient.prototype.getCurrentUserID = function () { var _this = this; return this.errorBoundary.capture('getCurrentUserID', function () { return _this.getUnitID(_this.getCurrentUser(), 'userid'); }, function () { return ''; }); }; StatsigClient.prototype.getUnitID = function (user, idType) { var _a, _b, _c; if (!user) { return null; } if (idType.toLowerCase() === 'userid') { return (_b = (_a = user.userID) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : null; } if (user.customIDs) { return (_c = user.customIDs[idType]) !== null && _c !== void 0 ? _c : user.customIDs[idType.toLowerCase()]; } return null; }; StatsigClient.prototype.getStatsigMetadata = function () { var _this = this; return this.errorBoundary.capture('getStatsigMetadata', function () { return _this.identity.getStatsigMetadata(); }, function () { return {}; }); }; StatsigClient.prototype.getSDKType = function () { var _this = this; return this.errorBoundary.capture('getSDKType', function () { return _this.identity.getSDKType(); }, function () { return ''; }); }; StatsigClient.prototype.getSDKVersion = function () { var _this = this; return this.errorBoundary.capture('getSDKVersion', function () { return _this.identity.getSDKVersion(); }, function () { return ''; }); }; StatsigClient.prototype.delayedSetup = function () { var _this = this; this.errorBoundary.swallow('delayedSetup', function () { if (_this.options.getInitializeValues() != null) { _this.fireAndForgetPrefechUsers(); } _this.identity.saveStableID(); _this.logger .sendSavedRequests() .catch(function (reason) { return _this.errorBoundary.logError('sendSavedRequests:delayedSetup', reason); }); }); }; StatsigClient.prototype.setInitializeValues = function (initializeValues) { var _this = this; this.errorBoundary.capture('setInitializeValues', function () { _this.store.bootstrap(initializeValues); var cb = null; if (!_this.ready) { // the sdk is usable and considered initialized when configured // with initializeValues _this.ready = true; _this.initCalled = true; // only callback on the first time initialize values are set and the // sdk is usable cb = _this.options.getInitCompletionCallback(); } // we wont have access to window/document/localStorage if these run on the server // so try to run whenever this is called _this.handleOptionalLogging(); _this.logger .sendSavedRequests() .catch(function (reason) { return _this.errorBoundary.logError('sendSavedRequests:setInitializeValues', reason); }); if (cb) { cb((0, Timing_1.now)() - _this.startTime, true, null); } }, function () { _this.ready = true; _this.initCalled = true; var cb = _this.options.getInitCompletionCallback(); if (cb) { cb((0, Timing_1.now)() - _this.startTime, false, 'Caught an exception during setInitializeValues'); } }); }; StatsigClient.prototype.initializeAsync = function () { return __awaiter(this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { return [2 /*return*/, this.errorBoundary.capture('initializeAsync', function () { return __awaiter(_this, void 0, void 0, function () { var handler, listener, user; var _this = this; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (this.pendingInitPromise != null) { return [2 /*return*/, this.pendingInitPromise]; } if (this.ready) { return [2 /*return*/, Promise.resolve()]; } Diagnostics_1.default.mark.overall.start({}); this.initCalled = true; if (!StatsigAsyncStorage_1.default.asyncStorage) return [3 /*break*/, 3]; return [4 /*yield*/, this.identity.initAsync()]; case 1: _b.sent(); return [4 /*yield*/, this.store.loadAsync()]; case 2: _b.sent(); _b.label = 3; case 3: (_a = this.onCacheLoadedForReact) === null || _a === void 0 ? void 0 : _a.call(this); if (this.appState != null) { handler = this.appState; if (handler.addEventListener && typeof handler.addEventListener === 'function') { this.currentAppState = handler.currentState; listener = handler.addEventListener('change', this.handleAppStateChange.bind(this)); this.appStateChangeSubscription = listener; } } if (this.options.getLocalModeEnabled()) { return [2 /*return*/, Promise.resolve()]; } user = this.identity.getUser(); this.pendingInitPromise = this.fetchAndSaveValues({ user: user, prefetchUsers: this.options.getPrefetchUsers(), timeout: this.options.getInitTimeoutMs(), }) .then(function () { Diagnostics_1.default.mark.overall.end({ success: true, evaluationDetails: _this.store.getGlobalEvaluationDetails(), }); return { success: true, message: null }; }) .catch(function (e) { var _a; Diagnostics_1.default.mark.overall.end({ success: false, error: Diagnostics_1.default.formatError(e), evaluationDetails: _this.store.getGlobalEvaluationDetails(), }); return { success: false, message: (_a = e.message) !== null && _a !== void 0 ? _a : null }; }) .then(function (_a) { var success = _a.success, message = _a.message; var cb = _this.options.getInitCompletionCallback(); if (cb) { cb((0, Timing_1.now)() - _this.startTime, success, message); } return; }) .finally(function () { _this.pendingInitPromise = null; _this.ready = true; _this.delayedSetup(); _this.logger.logDiagnostics(user, 'initialize'); }); this.handleOptionalLogging(); return [2 /*return*/, this.pendingInitPromise]; } }); }); }, function () { _this.ready = true; _this.initCalled = true; return Promise.resolve(); })]; }); }); }; StatsigClient.prototype.prefetchUsers = function (users) { return __awaiter(this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { return [2 /*return*/, this.errorBoundary.capture('prefetchUsers', function () { if (!users || users.length == 0) { return Promise.resolve(); } if (_this.options.getLocalModeEnabled()) { return Promise.resolve(); } return _this.fetchAndSaveValues({ user: null, prefetchUsers: users, timeout: 0, }); }, function () { return Promise.resolve(); })]; }); }); }; StatsigClient.prototype.getEvaluationDetails = function () { var _this = this; return this.errorBoundary.capture('getEvaluationDetails', function () { return _this.store.getGlobalEvaluationDetails(); }, function () { return { time: Date.now(), reason: EvaluationReason_1.EvaluationReason.Error, }; }); }; /** * Checks the value of a gate for the current user * @param {string} gateName - the name of the gate to check * @param {boolean} ignoreOverrides = false if this check should ignore local overrides * @returns {boolean} - value of a gate for the user. Gates are "off" (return false) by default * @throws Error if initialize() is not called first, or gateName is not a string */ StatsigClient.prototype.checkGate = function (gateName, ignoreOverrides) { var _this = this; if (ignoreOverrides === void 0) { ignoreOverrides = false; } return this.errorBoundary.capture('checkGate', function () { var _a, _b, _c; var result = _this.checkGateImpl(gateName, ignoreOverrides); _this.logGateExposureImpl(gateName, result); var cb = _this.options.getGateEvaluationCallback(); if (cb) { cb(gateName, result.gate.value, { withExposureLoggingDisabled: false, }); } var ecb = _this.options.getEvaluationCallback(); if (ecb) { var gate = new FeatureGate_1.default(gateName, result.gate.value, result.gate.rule_id, result.evaluationDetails, (_a = result.gate.group_name) !== null && _a !== void 0 ? _a : null, (_b = result.gate.id_type) !== null && _b !== void 0 ? _b : null, (_c = result.gate.secondary_exposures) !== null && _c !== void 0 ? _c : []); ecb({ type: 'gate', gate: gate }); } return result.gate.value === true; }, function () { return false; }, { configName: gateName }); }; /** * Gets the value and metadata of a gate evaluation for the current user * @param {string} gateName - the name of the gate to check * @returns {FeatureGate} - metadata about the value of the gate gate for the user. Gates are "off" (value false) by default * @throws Error if initialize() is not called first, or gateName is not a string */ StatsigClient.prototype.getFeatureGate = function (gateName, options) { var _this = this; if (options === void 0) { options = null; } return this.errorBoundary.capture('getFeatureGate', function () { var _a, _b, _c, _d, _e; var result = _this.checkGateImpl(gateName, (_a = options === null || options === void 0 ? void 0 : options.ignoreOverrides) !== null && _a !== void 0 ? _a : false); if (!(options === null || options === void 0 ? void 0 : options.disableExposureLogging)) { _this.logGateExposureImpl(gateName, result); } else { _this.logger.addNonExposedCheck(gateName); } var cb = _this.options.getGateEvaluationCallback(); if (cb) { cb(gateName, result.gate.value, { withExposureLoggingDisabled: (_b = options === null || options === void 0 ? void 0 : options.disableExposureLogging) !== null && _b !== void 0 ? _b : false, }); } var gate = new FeatureGate_1.default(gateName, result.gate.value, result.gate.rule_id, result.evaluationDetails, (_c = result.gate.group_name) !== null && _c !== void 0 ? _c : null, (_d = result.gate.id_type) !== null && _d !== void 0 ? _d : null, (_e = result.gate.secondary_exposures) !== null && _e !== void 0 ? _e : []); var ecb = _this.options.getEvaluationCallback(); if (ecb) { ecb({ type: 'gate', gate: gate }); } return gate; }, function () { return new FeatureGate_1.default(gateName, false, '', { reason: EvaluationReason_1.EvaluationReason.Error, time: Date.now(), }); }, { configName: gateName }); }; StatsigClient.prototype.checkGateWithExposureLoggingDisabled = function (gateName, ignoreOverrides) { var _this = this; if (ignoreOverrides === void 0) { ignoreOverrides = false; } return this.errorBoundary.capture('checkGateWithExposureLoggingDisabled', function () { var _a, _b, _c; _this.logger.addNonExposedCheck(gateName); var result = _this.checkGateImpl(gateName, ignoreOverrides); var cb = _this.options.getGateEvaluationCallback(); if (cb) { cb(gateName, result.gate.value, { withExposureLoggingDisabled: true, }); } var ecb = _this.options.getEvaluationCallback(); if (ecb) { var gate = new FeatureGate_1.default(gateName, result.gate.value, result.gate.rule_id, result.evaluationDetails, (_a = result.gate.group_name) !== null && _a !== void 0 ? _a : null, (_b = result.gate.id_type) !== null && _b !== void 0 ? _b : null, (_c = result.gate.secondary_exposures) !== null && _c !== void 0 ? _c : []); ecb({ type: 'gate', gate: gate }); } return result.gate.value === true; }, function () { return false; }); }; StatsigClient.prototype.logGateExposure = function (gateName) { var _this = this; this.errorBoundary.swallow('logGateExposure', function () { _this.logGateExposureImpl(gateName); }); }; /** * Checks the value of a config for the current user * @param {string} configName - the name of the config to get * @param {boolean} ignoreOverrides = false if this check should ignore local overrides * @returns {DynamicConfig} - value of a config for the user * @throws Error if initialize() is not called first, or configName is not a string */ StatsigClient.prototype.getConfig = function (configName, ignoreOverrides) { var _this = this; if (ignoreOverrides === void 0) { ignoreOverrides = false; } return this.errorBoundary.capture('getConfig', function () { var result = _this.getConfigImpl(configName, ignoreOverrides); _this.logConfigExposureImpl(configName, result); var ecb = _this.options.getEvaluationCallback(); if (ecb) { ecb({ type: 'config', config: result }); } return result; }, function () { return _this.getEmptyConfig(configName); }, { configName: configName }); }; StatsigClient.prototype.getConfigWithExposureLoggingDisabled = function (configName, ignoreOverrides) { var _this = this; if (ignoreOverrides === void 0) { ignoreOverrides = false; } return this.errorBoundary.capture('getConfig', function () { _this.logger.addNonExposedCheck(configName); var result = _this.getConfigImpl(configName, ignoreOverrides); var ecb = _this.options.getEvaluationCallback(); if (ecb) { ecb({ type: 'config', config: result }); } return result; }, function () { return _this.getEmptyConfig(configName); }); }; StatsigClient.prototype.logConfigExposure = function (configName) { var _this = this; this.errorBoundary.swallow('logConfigExposure', function () { _this.logConfigExposureImpl(configName); }); }; /** * Gets the experiment for a given user * @param {string} experimentName - the name of the experiment to get * @param {boolean} keepDeviceValue = false if this should use "sticky" values persisted in local storage * @param {boolean} ignoreOverrides = false if this check should ignore local overrides * @returns {DynamicConfig} - value of the experiment for the user, represented by a Dynamic Config object * @throws Error if initialize() is not called first, or experimentName is not a string */ StatsigClient.prototype.getExperiment = function (experimentName, keepDeviceValue, ignoreOverrides) { var _this = this; if (keepDeviceValue === void 0) { keepDeviceValue = false; } if (ignoreOverrides === void 0) { ignoreOverrides = false; } return this.errorBoundary.capture('getExperiment', function () { var result = _this.getExperimentImpl(experimentName, keepDeviceValue, ignoreOverrides); _this.logExperimentExposureImpl(experimentName, keepDeviceValue, result); var ecb = _this.options.getEvaluationCallback(); if (ecb) { ecb({ type: 'experiment', config: result }); } return result; }, function () { return _this.getEmptyConfig(experimentName); }, { configName: experimentName }); }; StatsigClient.prototype.getExperimentWithExposureLoggingDisabled = function (experimentName, keepDeviceValue, ignoreOverrides) { var _this = this; if (keepDeviceValue === void 0) { keepDeviceValue = false; } if (ignoreOverrides === void 0) { ignoreOverrides = false; } return this.errorBoundary.capture('getExperimentWithExposureLoggingDisabled', function () { _this.logger.addNonExposedCheck(experimentName); var result = _this.getExperimentImpl(experimentName, keepDeviceValue, ignoreOverrides); var ecb = _this.options.getEvaluationCallback(); if (ecb) { ecb({ type: 'experiment', config: result }); } return result; }, function () { return _this.getEmptyConfig(experimentName); }); }; StatsigClient.prototype.logExperimentExposure = function (experimentName, keepDeviceValue) { var _this = this; this.errorBoundary.swallow('logExperimentExposure', function () { _this.logExperimentExposureImpl(experimentName, keepDeviceValue); }); }; StatsigClient.prototype.getLayer = function (layerName, keepDeviceValue) { var _this = this; if (keepDeviceValue === void 0) { keepDeviceValue = false; } return this.errorBoundary.capture('getLayer', function () { var result = _this.getLayerImpl(_this.logLayerParameterExposureForLayer, layerName, keepDeviceValue); var ecb = _this.options.getEvaluationCallback(); if (ecb) { ecb({ type: 'layer', layer: result }); } return result; }, function () { return Layer_1.default._create(layerName, {}, '', _this.getEvalutionDetailsForError()); }, { configName: layerName }); }; StatsigClient.prototype.getLayerWithExposureLoggingDisabled = function (layerName, keepDeviceValue) { var _this = this; if (keepDeviceValue === void 0) { keepDeviceValue = false; } return this.errorBoundary.capture('getLayerWithExposureLoggingDisabled', function () { _this.logger.addNonExposedCheck(layerName); var result = _this.getLayerImpl(null, layerName, keepDeviceValue); var ecb = _this.options.getEvaluationCallback(); if (ecb) { ecb({ type: 'layer', layer: result }); } return result; }, function () { return Layer_1.default._create(layerName, {}, '', _this.getEvalutionDetailsForError()); }); }; StatsigClient.prototype.logLayerParameterExposure = function (layerName, parameterName, keepDeviceValue) { var _this = this; if (keepDeviceValue === void 0) { keepDeviceValue = false; } this.errorBoundary.swallow('logLayerParameterExposure', function () { var layer = _this.getLayerImpl(null, layerName, keepDeviceValue); _this.logLayerParameterExposureForLayer(layer, parameterName, true); }); }; StatsigClient.prototype.logEvent = function (eventName, value, metadata) { var _this = this; if (value === void 0) { value = null; } if (metadata === void 0) { metadata = null; } this.errorBoundary.swallow('logEvent', function () { if (!_this.logger || !_this.sdkKey) { throw new Errors_1.StatsigUninitializedError('Must initialize() before logging events.'); } if (typeof eventName !== 'string' || eventName.length === 0) { OutputLogger_1.default.error('Event not logged. No valid eventName passed.'); return; } if (_this.shouldTrimParam(eventName, MAX_VALUE_SIZE)) { OutputLogger_1.default.info('eventName is too long, trimming to ' + MAX_VALUE_SIZE + ' characters.'); eventName = eventName.substring(0, MAX_VALUE_SIZE); } if (typeof value === 'string' && _this.shouldTrimParam(value, MAX_VALUE_SIZE)) { OutputLogger_1.default.info('value is too long, trimming to ' + MAX_VALUE_SIZE + '.'); value = value.substring(0, MAX_VALUE_SIZE); } if (_this.shouldTrimParam(metadata, MAX_OBJ_SIZE)) { OutputLogger_1.default.info('metadata is too big. Dropping the metadata.'); metadata = { error: 'not logged due to size too large' }; } var event = new LogEvent_1.default(eventName); event.setValue(value); event.setMetadata(metadata); event.setUser(_this.getCurrentUser()); _this.logger.log(event); }); }; StatsigClient.prototype.updateUserWithValues = function (user, values) { var _this = this; // eslint-disable-next-line statsig-linter/public-methods-error-boundary var fireCompletionCallback; return this.errorBoundary.capture('updateUserWithValues', function () { var updateStartTime = Date.now(); if (!_this.initializeCalled()) { throw new Errors_1.StatsigUninitializedError('Call initialize() first.'); } fireCompletionCallback = function (success, error) { var cb = _this.options.getUpdateUserCompletionCallback(); cb === null || cb === void 0 ? void 0 : cb(Date.now() - updateStartTime, success, error); }; _this.identity.updateUser(_this.normalizeUser(user)); _this.store.bootstrap(values); _this.logger.resetDedupeKeys(); fireCompletionCallback(true, null); return true; }, function () { fireCompletionCallback === null || fireCompletionCallback === void 0 ? void 0 : fireCompletionCallback(false, 'Failed to update user. An unexpected error occured.'); return false; }); }; StatsigClient.prototype.updateUser = function (user) { return __awaiter(this, void 0, void 0, function () { var fireCompletionCallback; var _this = this; return __generator(this, function (_a) { return [2 /*return*/, this.errorBoundary.capture('updateUser', function () { return __awaiter(_this, void 0, void 0, function () { var updateStartTime, userCacheKey, isUserPrefetched, cachedTime, currentUser; var _this = this; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: updateStartTime = Date.now(); if (!this.initializeCalled()) { throw new Errors_1.StatsigUninitializedError('Call initialize() first.'); } fireCompletionCallback = function (success, error) { var cb = _this.options.getUpdateUserCompletionCallback(); cb === null || cb === void 0 ? void 0 : cb(Date.now() - updateStartTime, success, error); }; if (!(StatsigAsyncStorage_1.default.asyncStorage && ((_a = this.identity.getStatsigMetadata().stableID) !== null && _a !== void 0 ? _a : '') == '')) return [3 /*break*/, 2]; return [4 /*yield*/, this.identity.initAsync()]; case 1: _b.sent(); _b.label = 2; case 2: this.identity.updateUser(this.normalizeUser(user)); userCacheKey = this.getCurrentUserCacheKey(); isUserPrefetched = Boolean(this.prefetchedUsersByCacheKey[userCacheKey.v3]); cachedTime = this.store.updateUser(isUserPrefetched); Diagnostics_1.default.clearContext('api_call'); this.logger.resetDedupeKeys(); if (cachedTime != null && (isUserPrefetched || this.isCacheValidForFetchMode(cachedTime))) { fireCompletionCallback(true, null); return [2 /*return*/, Promise.resolve(true)]; } if (!(this.pendingInitPromise != null)) return [3 /*break*/, 4]; return [4 /*yield*/, this.pendingInitPromise]; case 3: _b.sent(); _b.label = 4; case 4: if (this.options.getLocalModeEnabled()) { fireCompletionCallback(true, null); return [2 /*return*/, Promise.resolve(true)]; } currentUser = this.identity.getUser(); this.pendingInitPromise = this.fetchAndSaveValues({ user: currentUser, prefetchUsers: [], timeout: undefined, }).finally(function () { _this.pendingInitPromise = null; }); return [2 /*return*/, this.pendingInitPromise .then(function () { fireCompletionCallback(true, null); return Promise.resolve(true); }) .catch(function (error) { fireCompletionCallback(false, "Failed to update user: ".concat(error.message)); return Promise.resolve(false); })]; } }); }); }, function () { fireCompletionCallback === null || fireCompletionCallback === void 0 ? void 0 : fireCompletionCallback(false, 'Failed to update user. An unexpected error occured.'); return Promise.resolve(false); })]; }); }); }; /** * Informs the statsig SDK that the client is closing or shutting down * so the SDK can clean up internal state */ StatsigClient.prototype.shutdown = function () { var _this = this; this.errorBoundary.swallow('shutdown', function () { _this.logger.shutdown(); if (_this.appStateChangeSubscription != null) { var sub = _this.appStateChangeSubscription; if (typeof sub.remove === 'function') { sub.remove(); } } StatsigLocalStorage_1.default.cleanup(); }); }; StatsigClient.prototype.getInitializeResponseJson = function () { var _this = this; return this.errorBoundary.capture('getInitializeResponseJson', function () { var _a; return { values: _this.store.getInitializeResponseJson(), evaluationDetails: (_a = _this.getEvaluationDetails()) !== null && _a !== void 0 ? _a : { reason: EvaluationReason_1.EvaluationReason.Uninitialized, time: 0, }, }; }, function () { var _a; return { values: '', evaluationDetails: (_a = _this.getEvaluationDetails()) !== null && _a !== void 0 ? _a : { reason: EvaluationReason_1.EvaluationReason.Uninitialized, time: 0, }, }; }); }; /** * Stores a local gate override * @param gateName the gate to override * @param value the value to override the gate to */ StatsigClient.prototype.overrideGate = function (gateName, value) { var _this = this; this.errorBoundary.swallow('overrideGate', function () { _this.ensureStoreLoaded(); _this.store.overrideGate(gateName, value); }); }; /** * Stores a local config override * @param configName the config to override * @param value the json value to override the config to */ StatsigClient.prototype.overrideConfig = function (configName, value) { var _this = this; this.errorBoundary.swallow('overrideConfig', function () { _this.ensureStoreLoaded(); _this.store.overrideConfig(configName, value); }); }; /** * Stores a local layer override * @param layerName the layer to override * @param value the json value to override the config to */ StatsigClient.prototype.overrideLayer = function (layerName, value) { var _this = this; this.errorBoundary.swallow('overrideLayer', function () { _this.ensureStoreLoaded(); _this.store.overrideLayer(layerName, value); }); }; /** * Removes the given gate override * @param gateName */ StatsigClient.prototype.removeGateOverride = function (gateName) { var _this = this; this.errorBoundary.swallow('removeGateOverride', function () { _this.ensureStoreLoaded(); _this.store.removeGateOverride(gateName); }); }; /** * Removes the given config override * @param configName */ StatsigClient.prototype.removeConfigOverride = function (configName) { var _this = this; this.errorBoundary.swallow('removeConfigOverride', function () { _this.ensureStoreLoaded(); _this.store.removeConfigOverride(configName); }); }; /** * Removes the given layer override * @param layerName */ StatsigClient.prototype.removeLayerOverride = function (layerName) { var _this = this; this.errorBoundary.swallow('removeLayerOverride', function () { _this.ensureStoreLoaded(); _this.store.removeLayerOverride(layerName); }); }; /** * @deprecated - use removeGateOverride or removeConfig override * Removes the given gate override * @param gateName */ StatsigClient.prototype.removeOverride = function (gateName) { var _this = this; this.errorBoundary.swallow('removeOverride', function () { _this.ensureStoreLoaded(); _this.store.removeGateOverride(gateName); }); }; /** * @deprecated - use getAllOverrides to get gate and config overrides * @returns Gate overrides */ StatsigClient.prototype.getOverrides = function () { var _this = this; return this.errorBoundary.capture('getOverrides', function () { _this.ensureStoreLoaded(); return _this.store.getAllOverrides().gates; }, function () { return ({}); }); }; /** * @returns The local gate and config overrides */ StatsigClient.prototype.getAllOverrides = function () { var _this = this; return this.errorBoundary.capture('getAllOverrides', function () { _this.ensureStoreLoaded(); return _this.store.getAllOverrides(); }, function () { return ({ gates: {}, configs: {}, layers: {} }); }); }; /** * @returns The Statsig stable ID used for device level experiments */ StatsigClient.prototype.getStableID = function () { var _this = this; return this.errorBoundary.capture('getStableID', function () { return _this.identity.getStatsigMetadata().stableID; }, function () { return ''; }); }; StatsigClient.prototype.initializeCalled = function () { return this.initCalled; }; // All methods below are for the statsig react native SDK internal usage only! /* eslint-disable statsig-linter/public-methods-error-boundary */ StatsigClient.prototype.setSDKPackageInfo = function (sdkPackageInfo) { if (sdkPackageInfo != null) { this.identity.setSDKPackageInfo(sdkPackageInfo); this.errorBoundary.setStatsigMetadata(this.getStatsigMetadata()); } }; /** * @params Debug information log with exposure event, and information will be living in metadata */ StatsigClient.prototype.setDebugInfo = function (debugInfo) { var _this = this; this.errorBoundary.capture('setDebuggingInfo', function () { if (!_this.initializeCalled()) { throw new Errors_1.StatsigUninitializedError('Call initialize() first.'); } _this.logger.setDebugInfo(debugInfo); }, function () { /* no-op */ }); }; StatsigClient.setAsyncStorage = function (asyncStorage) { if (asyncStorage != null) { StatsigAsyncStorage_1.default.asyncStorage = asyncStorage; } }; StatsigClient.prototype.setOnCacheLoadedReactCallback = function (fn) { this.onCacheLoadedForReact = fn !== null && fn !== void 0 ? fn : null; }; StatsigClient.setReactNativeUUID = function (uuid) { if (uuid != null) { StatsigClient.reactNativeUUID = uuid; } }; StatsigClient.prototype.setAppState = function (appState) { if (appState != null) { this.appState = appState; } }; StatsigClient.prototype.setNativeModules = function (nativeModules) { if (nativeModules != null) { this.identity.setNativeModules(nativeModules); } }; StatsigClient.prototype.setPlatform = function (platform) { if (platform != null) { this.identity.setPlatform(platform); } }; StatsigClient.prototype.setRNDeviceInfo = function (deviceInfo) { if (deviceInfo != null) { this.identity.setRNDeviceInfo(deviceInfo); } }; StatsigClient.prototype.setExpoConstants = function (expoConstants) { if (expoConstants != null) { this.identity.setExpoConstants(expoConstants); } }; StatsigClient.prototype.setExpoDevice = function (expoDevice) { if (expoDevice != null) { this.identity.setExpoDevice(expoDevice); } }; StatsigClient.prototype.flushEvents = function () { this.logger.flush(); }; StatsigClient.prototype.reenableAllLogging = function () { this.getOptions().reenableAllLogging(); }; StatsigClient.prototype.isCacheValidForFetchMode = function (cachedTime) { if (this.options.getFetchMode() !== 'cache-or-network') { return false; } // Only valid if the cache was during this session return cachedTime > this.startTime; }; StatsigClient.prototype.handleOptionalLogging = function () { var _this = this; var isErrorLoggingDisabled = this.options.getDisableErrorLogging(); var isAutoMetricsLoggingDisabled = this.options.getDisableAutoMetricsLogging(); if (isErrorLoggingDisabled && isAutoMetricsLoggingDisabled) { return; } if (this.optionalLoggingSetup || typeof window === 'undefined' || !window || !window.addEventListener) { return; } var user = this.identity.getUser(); if (!isErrorLoggingDisabled) { window.addEventListener('error', function (e) { var _a; var errorObj = e.error; if (errorObj != null && typeof errorObj === 'object') { try { errorObj = JSON.stringify(errorObj); } catch (e) { errorObj = 'Failed to stringify Error'; } } _this.logger.logAppError(user, (_a = e.message) !== null && _a !== void 0 ? _a : '', { filename: e.filename, lineno: e.lineno, colno: e.colno, error_obj: errorObj, }); }); } if (!isAutoMetricsLoggingDisabled) { if (typeof document === 'undefined' || !document || typeof setTimeout === 'undefined' || !setTimeout) { return; } var work_1 = function () { setTimeout(function () { _this.logger.logAppMetrics(user); }, 1000); }; if (document.readyState === 'complete') { work_1(); } else { window.addEventListener('load', function () { return work_1(); }); } } this.optionalLoggingSetup = true; }; StatsigClient.prototype.handleAppStateChan