UNPKG

statsig-js

Version:

Statsig JavaScript client SDK for single user environments.

1,002 lines 57 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 (_) 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 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 EvaluationReason_1 = require("./utils/EvaluationReason"); var Hashing_1 = require("./utils/Hashing"); var StatsigAsyncStorage_1 = __importDefault(require("./utils/StatsigAsyncStorage")); var StatsigLocalStorage_1 = __importDefault(require("./utils/StatsigLocalStorage")); var Diagnostics_1 = __importDefault(require("./utils/Diagnostics")); var ConsoleLogger_1 = __importDefault(require("./utils/ConsoleLogger")); var Timing_1 = require("./utils/Timing"); var ResponseVerification_1 = require("./utils/ResponseVerification"); 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.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); }; 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; this.consoleLogger = new ConsoleLogger_1.default(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.network = new StatsigNetwork_1.default(this); this.store = new StatsigStore_1.default(this, this.options.getInitializeValues()); this.errorBoundary.setStatsigMetadata(this.getStatsigMetadata()); 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.getConsoleLogger = function () { return this.consoleLogger; }; 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 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 && this.appState.addEventListener && typeof this.appState.addEventListener === 'function') { this.currentAppState = this.appState.currentState; this.appState.addEventListener('change', this.handleAppStateChange.bind(this)); } 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; _this.errorBoundary.logError('initializeAsync:fetchAndSaveValues', e); 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 () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { this.pendingInitPromise = null; this.ready = true; this.delayedSetup(); this.logger.logDiagnostics(user, 'initialize'); return [2 /*return*/]; }); }); }); 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; } 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 result = _this.checkGateImpl(gateName, ignoreOverrides); _this.logGateExposureImpl(gateName, result); var cb = _this.options.getGateEvaluationCallback(); if (cb) { cb(gateName, result.gate.value, { withExposureLoggingDisabled: false, }); } return result.gate.value === true; }, function () { return false; }, { configName: gateName }); }; StatsigClient.prototype.checkGateWithExposureLoggingDisabled = function (gateName, ignoreOverrides) { var _this = this; if (ignoreOverrides === void 0) { ignoreOverrides = false; } return this.errorBoundary.capture('checkGateWithExposureLoggingDisabled', function () { var result = _this.checkGateImpl(gateName, ignoreOverrides); var cb = _this.options.getGateEvaluationCallback(); if (cb) { cb(gateName, result.gate.value, { withExposureLoggingDisabled: true, }); } 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); 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 () { return _this.getConfigImpl(configName, ignoreOverrides); }, 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); 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 () { return _this.getExperimentImpl(experimentName, keepDeviceValue, ignoreOverrides); }, 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 () { return _this.getLayerImpl(_this.logLayerParameterExposureForLayer, layerName, keepDeviceValue); }, 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 () { return _this.getLayerImpl(null, layerName, keepDeviceValue); }, 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) { _this.consoleLogger.error('Event not logged. No valid eventName passed.'); return; } if (_this.shouldTrimParam(eventName, MAX_VALUE_SIZE)) { _this.consoleLogger.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)) { _this.consoleLogger.info('value is too long, trimming to ' + MAX_VALUE_SIZE + '.'); value = value.substring(0, MAX_VALUE_SIZE); } if (_this.shouldTrimParam(metadata, MAX_OBJ_SIZE)) { _this.consoleLogger.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); 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: " + error); 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.appState && _this.appState.removeEventListener && typeof _this.appState.removeEventListener === 'function') { _this.appState.removeEventListener('change', _this.handleAppStateChange.bind(_this)); } 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()); } }; 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.handleAppStateChange = function (nextAppState) { var _this = this; var _a; if (this.currentAppState === 'active' && nextAppState.match(/inactive|background/)) { this.logger.flush(true); } else if (((_a = this.currentAppState) === null || _a === void 0 ? void 0 : _a.match(/inactive|background/)) && nextAppState === 'active') { this.logger .sendSavedRequests() .catch(function (reason) { return _this.errorBoundary.logError('sendSavedRequests:handleAppStateChange', reason); }); } this.currentAppState = nextAppState; }; StatsigClient.prototype.shouldTrimParam = function (entity, size) { if (entity == null) return false; if (typeof entity === 'string') return entity.length > size; if (typeof entity === 'object') { return JSON.stringify(entity).length > size; } if (typeof entity === 'number') return entity.toString().length > size; return false; }; StatsigClient.prototype.normalizePrefetchUsers = function (users) { var _this = this; if (users == null) { return []; } return users.map(function (user) { return _this.normalizeUser(user); }); }; StatsigClient.prototype.normalizeUser = function (user) { var userCopy = {}; try { userCopy = JSON.parse(JSON.stringify(user)); } catch (error) { throw new Errors_1.StatsigInvalidArgumentError('User object must be convertable to JSON string.'); } userCopy = this.trimUserObjIfNeeded(userCopy); if (this.options.getEnvironment() != null) { userCopy.statsigEnvironment = this.options.getEnvironment(); } return userCopy; }; StatsigClient.prototype.trimUserObjIfNeeded = function (user) { var _a, _b; if (user == null) { return {}; } if (this.shouldTrimParam((_a = user.userID) !== null && _a !== void 0 ? _a : null, MAX_VALUE_SIZE)) { this.consoleLogger.info('User ID is too large, trimming to ' + MAX_VALUE_SIZE + 'characters'); user.userID = (_b = user.userID) === null || _b === void 0 ? void 0 : _b.toString().substring(0, MAX_VALUE_SIZE); } if (this.shouldTrimParam(user, MAX_OBJ_SIZE)) { user.custom = {}; if (this.shouldTrimParam(user, MAX_OBJ_SIZE)) { this.consoleLogger.info('User object is too large, only keeping the user ID.'); user = { userID: user.userID }; } else { this.consoleLogger.info('User object is too large, dropping the custom property.'); } } return user; }; StatsigClient.prototype.ensureStoreLoaded = function () { if (!this.store.isLoaded()) { throw new Errors_1.StatsigUninitializedError('Call and wait for initialize() to finish first.'); } }; StatsigClient.prototype.getEvalutionDetailsForError = function () { return { time: Date.now(), reason: EvaluationReason_1.EvaluationReason.Error, }; }; StatsigClient.prototype.fetchAndSaveValues = function (args) { var _a, _b, _c, _d, _e, _f; return __awaiter(this, void 0, void 0, function () { var user, prefetchUsers, timeout, keyedPrefetchUsers, sinceTime, previousDerivedFields; var _this = this; return __generator(this, function (_g) { user = args.user; prefetchUsers = (_a = args.prefetchUsers) !== null && _a !== void 0 ? _a : []; timeout = (_b = args.timeout) !== null && _b !== void 0 ? _b : this.options.getInitTimeoutMs(); if (prefetchUsers.length > 5) { this.consoleLogger.info('Cannot prefetch more than 5 users.'); } keyedPrefetchUsers = this.normalizePrefetchUsers(prefetchUsers) .slice(0, 5) .reduce(function (acc, curr) { acc[(0, Hashing_1.getUserCacheKey)(_this.getStableID(), curr, _this.getSDKKey()).v3] = curr; return acc; }, {}); sinceTime = null; if (prefetchUsers.length === 0) { sinceTime = this.store.getLastUpdateTime(user, String((_d = (_c = this.getStatsigMetadata()) === null || _c === void 0 ? void 0 : _c.stableID) !== null && _d !== void 0 ? _d : '')); } previousDerivedFields = this.store.getPreviousDerivedFields(user, String((_f = (_e = this.getStatsigMetadata()) === null || _e === void 0 ? void 0 : _e.stableID) !== null && _f !== void 0 ? _f : '')); return [2 /*return*/, this.network .fetchValues({ user: user, sinceTime: sinceTime, timeout: timeout, useDeltas: sinceTime != null, prefetchUsers: prefetchUsers.length > 0 ? keyedPref