@atlaskit/feature-gate-js-client
Advanced tools
Comparing version 4.23.4 to 4.24.0
# @atlaskit/feature-gate-js-client | ||
## 4.24.0 | ||
### Minor Changes | ||
- [#111947](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/111947) | ||
[`d9e24de5d5abe`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/d9e24de5d5abe) - | ||
Upgrades from the old deprecated statsig-js-lite library to the newer and more performant | ||
@statsig/js-client library while keeping the API identical to avoid a breaking change. | ||
Also exposes the client under @atlaskit/feature-gate-js-client/client so that consumers which need | ||
to (like Marketplace) can create their own client instance separate to the static client used by | ||
products. | ||
## 4.23.4 | ||
@@ -4,0 +17,0 @@ |
"use strict"; | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
var _typeof = require("@babel/runtime/helpers/typeof"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -9,2 +8,3 @@ value: true | ||
exports.Client = void 0; | ||
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); | ||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
@@ -16,10 +16,14 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _statsigJsLite = _interopRequireWildcard(require("statsig-js-lite")); | ||
var _jsClient = require("@statsig/js-client"); | ||
var _subscriptions = _interopRequireDefault(require("../subscriptions")); | ||
var _DynamicConfig = require("./compat/DynamicConfig"); | ||
var _Layer = require("./compat/Layer"); | ||
var _types = require("./compat/types"); | ||
var _fetcher = _interopRequireDefault(require("./fetcher")); | ||
var _types = require("./types"); | ||
var _NoFetchDataAdapter = require("./NoFetchDataAdapter"); | ||
var _PersistentOverrideAdapter = require("./PersistentOverrideAdapter"); | ||
var _types2 = require("./types"); | ||
var _utils = require("./utils"); | ||
var _version = require("./version"); | ||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } | ||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } | ||
var _excluded = ["sdkKey", "environment", "updateUserCompletionCallback", "perimeter"]; | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
@@ -29,5 +33,6 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
// default event logging api is Atlassian proxy rather than Statsig's domain, to avoid ad blockers | ||
var DEFAULT_EVENT_LOGGING_API = 'https://xp.atlassian.com/v1/'; | ||
var DEFAULT_EVENT_LOGGING_API = 'https://xp.atlassian.com/v1/rgstr'; | ||
var Client = exports.Client = /*#__PURE__*/function () { | ||
function Client() { | ||
var _this = this; | ||
(0, _classCallCheck2.default)(this, Client); | ||
@@ -49,2 +54,17 @@ (0, _defineProperty2.default)(this, "initPromise", null); | ||
(0, _defineProperty2.default)(this, "subscriptions", new _subscriptions.default()); | ||
(0, _defineProperty2.default)(this, "dataAdapter", new _NoFetchDataAdapter.NoFetchDataAdapter()); | ||
(0, _defineProperty2.default)(this, "overrideAdapter", new _PersistentOverrideAdapter.PersistentOverrideAdapter()); | ||
/** | ||
* Call this if modifying the values being served by the Statsig library since it has its own | ||
* memoization cache which will not be updated if the values are changed outside of the library. | ||
*/ | ||
(0, _defineProperty2.default)(this, "statsigValuesUpdated", function () { | ||
if (_this.user) { | ||
// Trigger a reset of the memoize cache | ||
_this.statsigClient.updateUserSync(_this.user, { | ||
disableBackgroundCacheRefresh: true | ||
}); | ||
} | ||
_this.subscriptions.anyUpdated(); | ||
}); | ||
} | ||
@@ -72,3 +92,3 @@ return (0, _createClass2.default)(Client, [{ | ||
var _initialize = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(clientOptions, identifiers, customAttributes) { | ||
var _this = this; | ||
var _this2 = this; | ||
var clientOptionsWithDefaults, startTime; | ||
@@ -92,8 +112,8 @@ return _regenerator.default.wrap(function _callee$(_context) { | ||
this.initPromise = this.init(clientOptionsWithDefaults, identifiers, customAttributes).then(function () { | ||
_this.initCompleted = true; | ||
_this.initWithDefaults = true; | ||
_this2.initCompleted = true; | ||
_this2.initWithDefaults = true; | ||
}).finally(function () { | ||
var endTime = performance.now(); | ||
var totalTime = endTime - startTime; | ||
_this.fireClientEvent(startTime, totalTime, 'initialize', _this.initCompleted, clientOptionsWithDefaults.apiKey); | ||
_this2.fireClientEvent(startTime, totalTime, 'initialize', _this2.initCompleted, clientOptionsWithDefaults.apiKey); | ||
}); | ||
@@ -134,3 +154,3 @@ return _context.abrupt("return", this.initPromise); | ||
var _initializeWithProvider = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(clientOptions, provider, identifiers, customAttributes) { | ||
var _this2 = this; | ||
var _this3 = this; | ||
var clientOptionsWithDefaults, startTime; | ||
@@ -159,8 +179,8 @@ return _regenerator.default.wrap(function _callee2$(_context2) { | ||
this.initPromise = this.initWithProvider(clientOptionsWithDefaults, provider, identifiers, customAttributes).then(function () { | ||
_this2.initCompleted = true; | ||
_this2.initWithDefaults = true; | ||
_this3.initCompleted = true; | ||
_this3.initWithDefaults = true; | ||
}).finally(function () { | ||
var endTime = performance.now(); | ||
var totalTime = endTime - startTime; | ||
_this2.fireClientEvent(startTime, totalTime, 'initializeWithProvider', _this2.initCompleted, provider.getApiKey ? provider.getApiKey() : undefined); | ||
_this3.fireClientEvent(startTime, totalTime, 'initializeWithProvider', _this3.initCompleted, provider.getApiKey ? provider.getApiKey() : undefined); | ||
}); | ||
@@ -184,4 +204,6 @@ return _context2.abrupt("return", this.initPromise); | ||
if (this.initCompleted || this.initWithDefaults) { | ||
_statsigJsLite.default.setInitializeValues(experimentsResult.experimentValues); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.dataAdapter.setBootstrapData(experimentsResult.experimentValues); | ||
this.dataAdapter.setData(JSON.stringify(experimentsResult.experimentValues)); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -197,7 +219,7 @@ } catch (error) { | ||
var _analyticsWebClient, | ||
_this3 = this; | ||
_this4 = this; | ||
var apiKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; | ||
(_analyticsWebClient = this.initOptions.analyticsWebClient) === null || _analyticsWebClient === void 0 || _analyticsWebClient.then(function (analyticsWebClient) { | ||
var attributes = _objectSpread({ | ||
targetApp: _this3.initOptions.targetApp, | ||
targetApp: _this4.initOptions.targetApp, | ||
clientVersion: _version.CLIENT_VERSION, | ||
@@ -218,3 +240,3 @@ success: success, | ||
}).catch(function (err) { | ||
if (_this3.initOptions.environment !== _types.FeatureGateEnvironment.Production) { | ||
if (_this4.initOptions.environment !== _types2.FeatureGateEnvironment.Production) { | ||
// eslint-disable-next-line no-console | ||
@@ -229,3 +251,3 @@ console.error('Analytics web client promise did not resolve', err); | ||
var _initializeFromValues = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(clientOptions, identifiers, customAttributes) { | ||
var _this4 = this; | ||
var _this5 = this; | ||
var initializeValues, | ||
@@ -250,14 +272,19 @@ clientOptionsWithDefaults, | ||
case 5: | ||
// This makes sure the new Statsig client behaves like the old when bootstrap data is | ||
// passed, and `has_updates` isn't specified (which happens a lot in product integration tests). | ||
if (!Object.prototype.hasOwnProperty.call(initializeValues, 'has_updates')) { | ||
initializeValues['has_updates'] = true; | ||
} | ||
startTime = performance.now(); | ||
this.initOptions = clientOptionsWithDefaults; | ||
this.initPromise = this.initFromValues(clientOptionsWithDefaults, identifiers, customAttributes, initializeValues).then(function () { | ||
_this4.initCompleted = true; | ||
_this4.initWithDefaults = true; | ||
_this5.initCompleted = true; | ||
_this5.initWithDefaults = true; | ||
}).finally(function () { | ||
var endTime = performance.now(); | ||
var totalTime = endTime - startTime; | ||
_this4.fireClientEvent(startTime, totalTime, 'initializeFromValues', _this4.initCompleted); | ||
_this5.fireClientEvent(startTime, totalTime, 'initializeFromValues', _this5.initCompleted); | ||
}); | ||
return _context3.abrupt("return", this.initPromise); | ||
case 9: | ||
case 10: | ||
case "end": | ||
@@ -273,2 +300,10 @@ return _context3.stop(); | ||
}() | ||
}, { | ||
key: "assertInitialized", | ||
value: function assertInitialized(statsigClient) { | ||
if (!statsigClient) { | ||
throw new Error('Client must be initialized before using this method'); | ||
} | ||
} | ||
/** | ||
@@ -288,2 +323,3 @@ * This method updates the user using a network call to fetch the new set of values. | ||
case 0: | ||
this.assertInitialized(this.statsigClient); | ||
fetchOptionsWithDefaults = (0, _utils.getOptionsWithDefaults)(fetchOptions); | ||
@@ -300,5 +336,5 @@ initializeValuesProducer = function initializeValuesProducer() { | ||
}; | ||
_context4.next = 4; | ||
_context4.next = 5; | ||
return this.updateUserUsingInitializeValuesProducer(initializeValuesProducer, identifiers, customAttributes); | ||
case 4: | ||
case 5: | ||
case "end": | ||
@@ -325,20 +361,21 @@ return _context4.stop(); | ||
var _updateUserWithProvider = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(identifiers, customAttributes) { | ||
var _this5 = this; | ||
var _this6 = this; | ||
return _regenerator.default.wrap(function _callee5$(_context5) { | ||
while (1) switch (_context5.prev = _context5.next) { | ||
case 0: | ||
this.assertInitialized(this.statsigClient); | ||
if (this.provider) { | ||
_context5.next = 2; | ||
_context5.next = 3; | ||
break; | ||
} | ||
throw new Error('Cannot update user using provider as the client was not initialised with a provider'); | ||
case 2: | ||
_context5.next = 4; | ||
case 3: | ||
_context5.next = 5; | ||
return this.provider.setProfile(this.initOptions, identifiers, customAttributes); | ||
case 4: | ||
_context5.next = 6; | ||
case 5: | ||
_context5.next = 7; | ||
return this.updateUserUsingInitializeValuesProducer(function () { | ||
return _this5.provider.getExperimentValues(); | ||
return _this6.provider.getExperimentValues(); | ||
}, identifiers, customAttributes); | ||
case 6: | ||
case 7: | ||
case "end": | ||
@@ -374,2 +411,3 @@ return _context5.stop(); | ||
initializeValues = _args6.length > 2 && _args6[2] !== undefined ? _args6[2] : {}; | ||
this.assertInitialized(this.statsigClient); | ||
initializeValuesProducer = function initializeValuesProducer() { | ||
@@ -381,5 +419,5 @@ return Promise.resolve({ | ||
}; | ||
_context6.next = 4; | ||
_context6.next = 5; | ||
return this.updateUserUsingInitializeValuesProducer(initializeValuesProducer, identifiers, customAttributes); | ||
case 4: | ||
case 5: | ||
case "end": | ||
@@ -420,6 +458,8 @@ return _context6.stop(); | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
var _options$fireGateExpo = options.fireGateExposure, | ||
fireGateExposure = _options$fireGateExpo === void 0 ? true : _options$fireGateExpo; | ||
var evalMethod = fireGateExposure ? _statsigJsLite.default.checkGate.bind(_statsigJsLite.default) : _statsigJsLite.default.checkGateWithExposureLoggingDisabled.bind(_statsigJsLite.default); | ||
return evalMethod(gateName); | ||
return this.statsigClient.checkGate(gateName, { | ||
disableExposureLog: !fireGateExposure | ||
}); | ||
} catch (error) { | ||
@@ -443,5 +483,7 @@ // Log the first occurrence of the error | ||
try { | ||
// @ts-expect-error TS2341: Property _getClientX is private and only accessible within class Statsi | ||
var gate = _statsigJsLite.default._getClientX()._getGateFromStore(gateName); | ||
return gate.evaluationDetails.reason !== _statsigJsLite.EvaluationReason.Unrecognized; | ||
this.assertInitialized(this.statsigClient); | ||
var gate = this.statsigClient.getFeatureGate(gateName, { | ||
disableExposureLog: true | ||
}); | ||
return !gate.details.reason.includes('Unrecognized'); | ||
} catch (error) { | ||
@@ -458,4 +500,7 @@ // eslint-disable-next-line no-console | ||
try { | ||
var config = _statsigJsLite.default.getExperimentWithExposureLoggingDisabled(experimentName); | ||
return config._evaluationDetails.reason !== _statsigJsLite.EvaluationReason.Unrecognized; | ||
this.assertInitialized(this.statsigClient); | ||
var config = this.statsigClient.getExperiment(experimentName, { | ||
disableExposureLog: true | ||
}); | ||
return !config.details.reason.includes('Unrecognized'); | ||
} catch (error) { | ||
@@ -478,3 +523,6 @@ // eslint-disable-next-line no-console | ||
value: function manuallyLogGateExposure(gateName) { | ||
_statsigJsLite.default.manuallyLogGateExposure(gateName); | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
this.statsigClient.checkGate(gateName); | ||
} | ||
@@ -502,6 +550,8 @@ | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
var _options$fireExperime = options.fireExperimentExposure, | ||
fireExperimentExposure = _options$fireExperime === void 0 ? true : _options$fireExperime; | ||
var evalMethod = fireExperimentExposure ? _statsigJsLite.default.getExperiment.bind(_statsigJsLite.default) : _statsigJsLite.default.getExperimentWithExposureLoggingDisabled.bind(_statsigJsLite.default); | ||
return evalMethod(experimentName); | ||
return _DynamicConfig.DynamicConfig.fromExperiment(this.statsigClient.getExperiment(experimentName, { | ||
disableExposureLog: !fireExperimentExposure | ||
})); | ||
} catch (error) { | ||
@@ -520,5 +570,5 @@ // Log the first occurrence of the error | ||
// Return a default value | ||
return new _statsigJsLite.DynamicConfig(experimentName, {}, '', { | ||
return new _DynamicConfig.DynamicConfig(experimentName, {}, '', { | ||
time: Date.now(), | ||
reason: _statsigJsLite.EvaluationReason.Error | ||
reason: _types.EvaluationReason.Error | ||
}); | ||
@@ -597,3 +647,6 @@ } | ||
value: function manuallyLogExperimentExposure(experimentName) { | ||
_statsigJsLite.default.manuallyLogExperimentExposure(experimentName); | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
this.statsigClient.getExperiment(experimentName); | ||
} | ||
@@ -610,3 +663,7 @@ | ||
value: function manuallyLogLayerExposure(layerName, parameterName) { | ||
_statsigJsLite.default.manuallyLogLayerParameterExposure(layerName, parameterName); | ||
var _this$statsigClient$g; | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
(_this$statsigClient$g = this.statsigClient.getLayer(layerName)) === null || _this$statsigClient$g === void 0 || _this$statsigClient$g.get(parameterName); | ||
} | ||
@@ -616,3 +673,4 @@ }, { | ||
value: function shutdownStatsig() { | ||
_statsigJsLite.default.shutdown(); | ||
this.assertInitialized(this.statsigClient); | ||
this.statsigClient.shutdown(); | ||
} | ||
@@ -626,3 +684,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -639,4 +697,11 @@ * is called. If you are using this API for testing purposes, you should call | ||
value: function overrideGate(gateName, value) { | ||
_statsigJsLite.default.overrideGate(gateName, value); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.overrideGate(gateName, value); | ||
// Trigger a reset of the memoized gate value | ||
if (this.user) { | ||
this.statsigClient.updateUserSync(this.user, { | ||
disableBackgroundCacheRefresh: true | ||
}); | ||
} | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -650,4 +715,5 @@ | ||
value: function clearGateOverride(gateName) { | ||
_statsigJsLite.default.overrideGate(gateName, null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeGateOverride(gateName); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -661,3 +727,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -674,4 +740,5 @@ * is called. If you are using this API for testing purposes, you should call | ||
value: function overrideConfig(experimentName, values) { | ||
_statsigJsLite.default.overrideConfig(experimentName, values); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.overrideDynamicConfig(experimentName, values); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -686,4 +753,5 @@ | ||
value: function clearConfigOverride(experimentName) { | ||
_statsigJsLite.default.overrideConfig(experimentName, null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeDynamicConfigOverride(experimentName); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -698,3 +766,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -708,8 +776,5 @@ * is called. If you are using this API for testing purposes, you should call | ||
value: function setOverrides(overrides) { | ||
_statsigJsLite.default.setOverrides(_objectSpread({ | ||
gates: {}, | ||
configs: {}, | ||
layers: {} | ||
}, overrides)); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.setOverrides(overrides); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -723,3 +788,4 @@ | ||
value: function getOverrides() { | ||
return _statsigJsLite.default.getOverrides(); | ||
this.assertInitialized(this.statsigClient); | ||
return this.overrideAdapter.getOverrides(); | ||
} | ||
@@ -733,4 +799,5 @@ | ||
value: function clearAllOverrides() { | ||
_statsigJsLite.default.setOverrides(null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeAllOverrides(); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -766,3 +833,3 @@ | ||
value: function onGateUpdated(gateName, callback) { | ||
var _this6 = this; | ||
var _this7 = this; | ||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
@@ -773,3 +840,3 @@ var wrapCallback = function wrapCallback(value) { | ||
if (fireGateExposure) { | ||
_this6.manuallyLogGateExposure(gateName); | ||
_this7.manuallyLogGateExposure(gateName); | ||
} | ||
@@ -798,3 +865,3 @@ try { | ||
value: function onExperimentValueUpdated(experimentName, parameterName, defaultValue, callback) { | ||
var _this7 = this; | ||
var _this8 = this; | ||
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; | ||
@@ -805,3 +872,3 @@ var wrapCallback = function wrapCallback(value) { | ||
if (fireExperimentExposure) { | ||
_this7.manuallyLogExperimentExposure(experimentName); | ||
_this8.manuallyLogExperimentExposure(experimentName); | ||
} | ||
@@ -815,3 +882,3 @@ try { | ||
}; | ||
return this.subscriptions.onExperimentValueUpdated(experimentName, parameterName, defaultValue, wrapCallback, this.getExperimentValue, options); | ||
return this.subscriptions.onExperimentValueUpdated(experimentName, parameterName, defaultValue, wrapCallback, this.getExperimentValue.bind(this), options); | ||
} | ||
@@ -968,5 +1035,10 @@ | ||
var _initFromValues = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee9(clientOptions, identifiers, customAttributes) { | ||
var _newClientOptions$net; | ||
var initializeValues, | ||
user, | ||
newClientOptions, | ||
sdkKey, | ||
environment, | ||
_updateUserCompletionCallback, | ||
_perimeter, | ||
restClientOptions, | ||
statsigOptions, | ||
@@ -978,26 +1050,39 @@ _args9 = arguments; | ||
initializeValues = _args9.length > 3 && _args9[3] !== undefined ? _args9[3] : {}; | ||
user = (0, _utils.toStatsigUser)(identifiers, customAttributes); | ||
this.overrideAdapter.initFromStoredOverrides(); | ||
this.user = (0, _utils.toStatsigUser)(identifiers, customAttributes); | ||
this.currentIdentifiers = identifiers; | ||
this.currentAttributes = customAttributes; | ||
if (!clientOptions.sdkKey) { | ||
clientOptions.sdkKey = DEFAULT_CLIENT_KEY; | ||
newClientOptions = (0, _utils.migrateInitializationOptions)(clientOptions); | ||
if (!newClientOptions.sdkKey) { | ||
newClientOptions.sdkKey = DEFAULT_CLIENT_KEY; | ||
} | ||
if (!clientOptions.eventLoggingApi) { | ||
clientOptions.eventLoggingApi = DEFAULT_EVENT_LOGGING_API; | ||
if (!((_newClientOptions$net = newClientOptions.networkConfig) !== null && _newClientOptions$net !== void 0 && _newClientOptions$net.logEventUrl)) { | ||
newClientOptions.networkConfig = _objectSpread(_objectSpread({}, newClientOptions.networkConfig), {}, { | ||
logEventUrl: DEFAULT_EVENT_LOGGING_API | ||
}); | ||
} | ||
if (clientOptions.perimeter === _types.PerimeterType.FEDRAMP_MODERATE) { | ||
if (newClientOptions.perimeter === _types2.PerimeterType.FEDRAMP_MODERATE) { | ||
// disable all logging in FedRAMP to prevent egress of sensitive data | ||
clientOptions.disableAllLogging = true; | ||
newClientOptions.disableLogging = true; | ||
} | ||
sdkKey = clientOptions.sdkKey; | ||
statsigOptions = (0, _utils.toStatsigOptions)(clientOptions, initializeValues); | ||
_context9.prev = 9; | ||
_context9.next = 12; | ||
return _statsigJsLite.default.initialize(sdkKey, user, statsigOptions); | ||
case 12: | ||
_context9.next = 22; | ||
sdkKey = newClientOptions.sdkKey, environment = newClientOptions.environment, _updateUserCompletionCallback = newClientOptions.updateUserCompletionCallback, _perimeter = newClientOptions.perimeter, restClientOptions = (0, _objectWithoutProperties2.default)(newClientOptions, _excluded); | ||
statsigOptions = _objectSpread(_objectSpread({}, restClientOptions), {}, { | ||
environment: { | ||
tier: environment | ||
}, | ||
includeCurrentPageUrlWithEvents: false, | ||
dataAdapter: this.dataAdapter, | ||
overrideAdapter: this.overrideAdapter | ||
}); | ||
_context9.prev = 11; | ||
this.statsigClient = new _jsClient.StatsigClient(sdkKey, this.user, statsigOptions); | ||
this.dataAdapter.setBootstrapData(initializeValues); | ||
_context9.next = 16; | ||
return this.statsigClient.initializeAsync(); | ||
case 16: | ||
_context9.next = 28; | ||
break; | ||
case 14: | ||
_context9.prev = 14; | ||
_context9.t0 = _context9["catch"](9); | ||
case 18: | ||
_context9.prev = 18; | ||
_context9.t0 = _context9["catch"](11); | ||
if (_context9.t0 instanceof Error) { | ||
@@ -1009,14 +1094,14 @@ // eslint-disable-next-line no-console | ||
console.warn("Initialising Statsig client with default sdk key and without values"); | ||
_context9.next = 20; | ||
return _statsigJsLite.default.initialize(DEFAULT_CLIENT_KEY, user, _objectSpread(_objectSpread({}, statsigOptions), {}, { | ||
initializeValues: {} | ||
})); | ||
case 20: | ||
this.statsigClient = new _jsClient.StatsigClient(DEFAULT_CLIENT_KEY, this.user, statsigOptions); | ||
this.dataAdapter.setBootstrapData(); | ||
_context9.next = 26; | ||
return this.statsigClient.initializeAsync(); | ||
case 26: | ||
this.initWithDefaults = true; | ||
throw _context9.t0; | ||
case 22: | ||
case 28: | ||
case "end": | ||
return _context9.stop(); | ||
} | ||
}, _callee9, this, [[9, 14]]); | ||
}, _callee9, this, [[11, 18]]); | ||
})); | ||
@@ -1044,3 +1129,3 @@ function initFromValues(_x25, _x26, _x27) { | ||
var _updateUserUsingInitializeValuesProducer = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee11(getInitializeValues, identifiers, customAttributes) { | ||
var _this8 = this; | ||
var _this9 = this; | ||
var originalInitPromise, initializeValuesPromise, updateUserPromise; | ||
@@ -1050,26 +1135,27 @@ return _regenerator.default.wrap(function _callee11$(_context11) { | ||
case 0: | ||
this.assertInitialized(this.statsigClient); | ||
if (this.initPromise) { | ||
_context11.next = 2; | ||
_context11.next = 3; | ||
break; | ||
} | ||
throw new Error('The client must be initialized before you can update the user.'); | ||
case 2: | ||
case 3: | ||
if (!this.isCurrentUser(identifiers, customAttributes)) { | ||
_context11.next = 4; | ||
_context11.next = 5; | ||
break; | ||
} | ||
return _context11.abrupt("return", this.initPromise); | ||
case 4: | ||
case 5: | ||
// Wait for the current initialize/update to finish | ||
originalInitPromise = this.initPromise; | ||
_context11.prev = 5; | ||
_context11.next = 8; | ||
_context11.prev = 6; | ||
_context11.next = 9; | ||
return this.initPromise; | ||
case 8: | ||
_context11.next = 12; | ||
case 9: | ||
_context11.next = 13; | ||
break; | ||
case 10: | ||
_context11.prev = 10; | ||
_context11.t0 = _context11["catch"](5); | ||
case 12: | ||
case 11: | ||
_context11.prev = 11; | ||
_context11.t0 = _context11["catch"](6); | ||
case 13: | ||
initializeValuesPromise = getInitializeValues(); | ||
@@ -1084,6 +1170,6 @@ updateUserPromise = this.updateStatsigClientUser(initializeValuesPromise, identifiers, customAttributes); // We replace the init promise here since we are essentially re-initializing the client at this | ||
// If the update failed then it changed nothing, so revert back to the original promise. | ||
_this8.initPromise = originalInitPromise; | ||
_this9.initPromise = originalInitPromise; | ||
// Set the user profile again to revert back to the current user | ||
if (!_this8.provider) { | ||
if (!_this9.provider) { | ||
_context10.next = 4; | ||
@@ -1093,3 +1179,3 @@ break; | ||
_context10.next = 4; | ||
return _this8.provider.setProfile(_this8.initOptions, _this8.currentIdentifiers, _this8.currentAttributes); | ||
return _this9.provider.setProfile(_this9.initOptions, _this9.currentIdentifiers, _this9.currentAttributes); | ||
case 4: | ||
@@ -1102,7 +1188,7 @@ case "end": | ||
return _context11.abrupt("return", updateUserPromise); | ||
case 16: | ||
case 17: | ||
case "end": | ||
return _context11.stop(); | ||
} | ||
}, _callee11, this, [[5, 10]]); | ||
}, _callee11, this, [[6, 11]]); | ||
})); | ||
@@ -1127,17 +1213,19 @@ function updateUserUsingInitializeValuesProducer(_x28, _x29, _x30) { | ||
var _updateStatsigClientUser = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee12(initializeValuesPromise, identifiers, customAttributes) { | ||
var initializeValues, user, _updateUserCompletion, _ref3, errMsg, success; | ||
var _this$initOptions, _this$initOptions$upd; | ||
var initializeValues, user, _updateUserCompletion, _ref3, errMsg, success, errorMessage; | ||
return _regenerator.default.wrap(function _callee12$(_context12) { | ||
while (1) switch (_context12.prev = _context12.next) { | ||
case 0: | ||
_context12.prev = 0; | ||
_context12.next = 3; | ||
this.assertInitialized(this.statsigClient); | ||
_context12.prev = 1; | ||
_context12.next = 4; | ||
return initializeValuesPromise; | ||
case 3: | ||
case 4: | ||
initializeValues = _context12.sent; | ||
user = (0, _utils.toStatsigUser)(identifiers, initializeValues.customAttributesFromFetch); | ||
_context12.next = 12; | ||
_context12.next = 13; | ||
break; | ||
case 7: | ||
_context12.prev = 7; | ||
_context12.t0 = _context12["catch"](0); | ||
case 8: | ||
_context12.prev = 8; | ||
_context12.t0 = _context12["catch"](1); | ||
// Make sure the updateUserCompletionCallback is called for any errors in our custom code. | ||
@@ -1149,6 +1237,22 @@ // This is not necessary for the updateUserWithValues call, because the Statsig client will | ||
throw _context12.t0; | ||
case 12: | ||
success = _statsigJsLite.default.updateUserWithValues(user, initializeValues.experimentValues); | ||
case 13: | ||
success = true; | ||
errorMessage = null; | ||
_context12.prev = 15; | ||
this.dataAdapter.setBootstrapData(initializeValues.experimentValues); | ||
this.user = user; | ||
_context12.next = 20; | ||
return this.statsigClient.updateUserAsync(this.user); | ||
case 20: | ||
_context12.next = 26; | ||
break; | ||
case 22: | ||
_context12.prev = 22; | ||
_context12.t1 = _context12["catch"](15); | ||
success = false; | ||
errorMessage = String(_context12.t1); | ||
case 26: | ||
(_this$initOptions = this.initOptions) === null || _this$initOptions === void 0 || (_this$initOptions$upd = _this$initOptions.updateUserCompletionCallback) === null || _this$initOptions$upd === void 0 || _this$initOptions$upd.call(_this$initOptions, success, errorMessage); | ||
if (!success) { | ||
_context12.next = 19; | ||
_context12.next = 33; | ||
break; | ||
@@ -1159,11 +1263,11 @@ } | ||
this.subscriptions.anyUpdated(); | ||
_context12.next = 20; | ||
_context12.next = 34; | ||
break; | ||
case 19: | ||
case 33: | ||
throw new Error('Failed to update user. An unexpected error occured.'); | ||
case 20: | ||
case 34: | ||
case "end": | ||
return _context12.stop(); | ||
} | ||
}, _callee12, this, [[0, 7]]); | ||
}, _callee12, this, [[1, 8], [15, 22]]); | ||
})); | ||
@@ -1174,10 +1278,10 @@ function updateStatsigClientUser(_x31, _x32, _x33) { | ||
return updateStatsigClientUser; | ||
}() | ||
}()) | ||
}, { | ||
key: "getPackageVersion", | ||
value: | ||
/** | ||
* @returns string version of the current package in semver style. | ||
*/ | ||
) | ||
}, { | ||
key: "getPackageVersion", | ||
value: function getPackageVersion() { | ||
function getPackageVersion() { | ||
return _version.CLIENT_VERSION; | ||
@@ -1207,6 +1311,8 @@ } | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
var _options$fireLayerExp = options.fireLayerExposure, | ||
fireLayerExposure = _options$fireLayerExp === void 0 ? true : _options$fireLayerExp; | ||
var evalMethod = fireLayerExposure ? _statsigJsLite.default.getLayer.bind(_statsigJsLite.default) : _statsigJsLite.default.getLayerWithExposureLoggingDisabled.bind(_statsigJsLite.default); | ||
return evalMethod(layerName); | ||
return _Layer.Layer.fromLayer(this.statsigClient.getLayer(layerName, { | ||
disableExposureLog: !fireLayerExposure | ||
})); | ||
} catch (error) { | ||
@@ -1225,6 +1331,5 @@ // Log the first occurrence of the error | ||
// Return a default value | ||
return _statsigJsLite.Layer._create(layerName, {}, '', { | ||
time: Date.now(), | ||
reason: _statsigJsLite.EvaluationReason.Error | ||
}); | ||
return _Layer.Layer.fromLayer((0, _jsClient._makeLayer)(layerName, { | ||
reason: 'Error' | ||
}, null)); | ||
} | ||
@@ -1231,0 +1336,0 @@ } |
@@ -16,3 +16,3 @@ "use strict"; | ||
get: function get() { | ||
return _statsigJsLite.DynamicConfig; | ||
return _DynamicConfig.DynamicConfig; | ||
} | ||
@@ -23,3 +23,3 @@ }); | ||
get: function get() { | ||
return _statsigJsLite.EvaluationReason; | ||
return _types.EvaluationReason; | ||
} | ||
@@ -30,3 +30,3 @@ }); | ||
get: function get() { | ||
return _types.FeatureGateEnvironment; | ||
return _types2.FeatureGateEnvironment; | ||
} | ||
@@ -37,3 +37,3 @@ }); | ||
get: function get() { | ||
return _types.PerimeterType; | ||
return _types2.PerimeterType; | ||
} | ||
@@ -47,4 +47,5 @@ }); | ||
var _version = require("./version"); | ||
var _statsigJsLite = require("statsig-js-lite"); | ||
var _types = require("./types"); | ||
var _types = require("./compat/types"); | ||
var _DynamicConfig = require("./compat/DynamicConfig"); | ||
var _types2 = require("./types"); | ||
var _FeatureGates; | ||
@@ -115,17 +116,14 @@ /** | ||
// Log the first occurrence of the error | ||
if (!_FeatureGates.hasCheckGateErrorOccurred) { | ||
// Log the first occurrence of the error | ||
if (!_FeatureGates.hasGetExperimentValueErrorOccurred) { | ||
// eslint-disable-next-line no-console | ||
console.warn({ | ||
msg: 'An error has occurred getting the experiment value from criterion override. Only the first occurrence of this error is logged.', | ||
experimentName: experimentName, | ||
defaultValue: defaultValue, | ||
options: options, | ||
error: error | ||
}); | ||
_FeatureGates.hasGetExperimentValueErrorOccurred = true; | ||
} | ||
return defaultValue; | ||
if (!_FeatureGates.hasGetExperimentValueErrorOccurred) { | ||
// eslint-disable-next-line no-console | ||
console.warn({ | ||
msg: 'An error has occurred getting the experiment value from criterion override. Only the first occurrence of this error is logged.', | ||
experimentName: experimentName, | ||
defaultValue: defaultValue, | ||
options: options, | ||
error: error | ||
}); | ||
_FeatureGates.hasGetExperimentValueErrorOccurred = true; | ||
} | ||
return defaultValue; | ||
} | ||
@@ -132,0 +130,0 @@ |
@@ -7,3 +7,3 @@ "use strict"; | ||
}); | ||
exports.toStatsigUser = exports.toStatsigUpdateUserCompletionCallback = exports.toStatsigOptions = exports.shallowEquals = exports.getOptionsWithDefaults = void 0; | ||
exports.toStatsigUser = exports.shallowEquals = exports.migrateInitializationOptions = exports.migrateEvaluationDetails = exports.getOptionsWithDefaults = void 0; | ||
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); | ||
@@ -13,4 +13,5 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); | ||
var _atlassianContext = require("@atlaskit/atlassian-context"); | ||
var _types = require("./types"); | ||
var _excluded = ["sdkKey", "updateUserCompletionCallback", "perimeter"]; | ||
var _types = require("./compat/types"); | ||
var _types2 = require("./types"); | ||
var _excluded = ["api", "disableCurrentPageLogging", "loggingIntervalMillis", "loggingBufferMaxSize", "localMode", "eventLoggingApi", "eventLoggingApiForRetries", "disableLocalStorage", "ignoreWindowUndefined", "disableAllLogging", "initTimeoutMs", "disableNetworkKeepalive", "overrideStableID", "disableErrorLogging", "disableAutoMetricsLogging"]; | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
@@ -24,3 +25,3 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
*/ | ||
perimeter: (0, _atlassianContext.isFedRamp)() ? _types.PerimeterType.FEDRAMP_MODERATE : _types.PerimeterType.COMMERCIAL | ||
perimeter: (0, _atlassianContext.isFedRamp)() ? _types2.PerimeterType.FEDRAMP_MODERATE : _types2.PerimeterType.COMMERCIAL | ||
}, options); | ||
@@ -75,36 +76,50 @@ }; | ||
}; | ||
/** | ||
* This method transforms the options given by the user into the format accepted by the Statsig | ||
* client. | ||
*/ | ||
var toStatsigOptions = exports.toStatsigOptions = function toStatsigOptions(options, initializeValues) { | ||
var sdkKey = options.sdkKey, | ||
updateUserCompletionCallback = options.updateUserCompletionCallback, | ||
perimeter = options.perimeter, | ||
restClientOptions = (0, _objectWithoutProperties2.default)(options, _excluded); | ||
return _objectSpread(_objectSpread({}, restClientOptions), {}, { | ||
initializeValues: initializeValues, | ||
environment: { | ||
tier: options.environment | ||
var migrateInitializationOptions = exports.migrateInitializationOptions = function migrateInitializationOptions(options) { | ||
var api = options.api, | ||
disableCurrentPageLogging = options.disableCurrentPageLogging, | ||
loggingIntervalMillis = options.loggingIntervalMillis, | ||
loggingBufferMaxSize = options.loggingBufferMaxSize, | ||
localMode = options.localMode, | ||
eventLoggingApi = options.eventLoggingApi, | ||
eventLoggingApiForRetries = options.eventLoggingApiForRetries, | ||
disableLocalStorage = options.disableLocalStorage, | ||
ignoreWindowUndefined = options.ignoreWindowUndefined, | ||
disableAllLogging = options.disableAllLogging, | ||
_initTimeoutMs = options.initTimeoutMs, | ||
_disableNetworkKeepalive = options.disableNetworkKeepalive, | ||
_overrideStableID = options.overrideStableID, | ||
_disableErrorLogging = options.disableErrorLogging, | ||
_disableAutoMetricsLogging = options.disableAutoMetricsLogging, | ||
rest = (0, _objectWithoutProperties2.default)(options, _excluded); | ||
return _objectSpread(_objectSpread({}, rest), {}, { | ||
networkConfig: { | ||
api: api, | ||
logEventUrl: eventLoggingApi ? eventLoggingApi + 'rgstr' : undefined, | ||
logEventFallbackUrls: eventLoggingApiForRetries ? [eventLoggingApiForRetries] : undefined, | ||
preventAllNetworkTraffic: localMode || !ignoreWindowUndefined && typeof window === 'undefined' | ||
}, | ||
disableCurrentPageLogging: true | ||
}, options.updateUserCompletionCallback && { | ||
updateUserCompletionCallback: toStatsigUpdateUserCompletionCallback(options.updateUserCompletionCallback) | ||
includeCurrentPageUrlWithEvents: !disableCurrentPageLogging, | ||
loggingIntervalMs: loggingIntervalMillis, | ||
loggingBufferMaxSize: loggingBufferMaxSize, | ||
disableStorage: disableLocalStorage, | ||
disableLogging: disableAllLogging | ||
}); | ||
}; | ||
/** | ||
* This method transforms an UpdateUserCompletionCallback in our own format into the format | ||
* accepted by the Statsig client. | ||
*/ | ||
var toStatsigUpdateUserCompletionCallback = exports.toStatsigUpdateUserCompletionCallback = function toStatsigUpdateUserCompletionCallback(callback) { | ||
/** | ||
* The duration passed to the callback indicates how long the update took, but it is deceptive | ||
* since it only times the Statsig code and doesn't account for all of the extra custom work we | ||
* do to obtain the bootstrap values. As a result, we just suppress this parameter in our own | ||
* callback rather than trying to keep it accurate. | ||
*/ | ||
return function (_duration, success, message) { | ||
callback(success, message); | ||
var evaluationReasonMappings = Object.entries(_types.EvaluationReason).map(function (_ref5) { | ||
var _ref6 = (0, _slicedToArray2.default)(_ref5, 2), | ||
key = _ref6[0], | ||
value = _ref6[1]; | ||
return [key.toLowerCase(), value]; | ||
}); | ||
var migrateEvaluationDetails = exports.migrateEvaluationDetails = function migrateEvaluationDetails(details) { | ||
var _evaluationReasonMapp, _evaluationReasonMapp2, _details$receivedAt; | ||
var reasonLower = details.reason.toLowerCase(); | ||
return { | ||
reason: (_evaluationReasonMapp = (_evaluationReasonMapp2 = evaluationReasonMappings.find(function (_ref7) { | ||
var _ref8 = (0, _slicedToArray2.default)(_ref7, 1), | ||
key = _ref8[0]; | ||
return reasonLower.includes(key); | ||
})) === null || _evaluationReasonMapp2 === void 0 ? void 0 : _evaluationReasonMapp2[1]) !== null && _evaluationReasonMapp !== void 0 ? _evaluationReasonMapp : _types.EvaluationReason.Unknown, | ||
time: (_details$receivedAt = details.receivedAt) !== null && _details$receivedAt !== void 0 ? _details$receivedAt : Date.now() | ||
}; | ||
}; |
@@ -8,2 +8,2 @@ "use strict"; | ||
/// <reference types="node" /> | ||
var CLIENT_VERSION = exports.CLIENT_VERSION = "4.23.4"; | ||
var CLIENT_VERSION = exports.CLIENT_VERSION = "4.24.0"; |
@@ -16,3 +16,3 @@ "use strict"; | ||
get: function get() { | ||
return _FeatureGates.DynamicConfig; | ||
return _DynamicConfig.DynamicConfig; | ||
} | ||
@@ -23,3 +23,3 @@ }); | ||
get: function get() { | ||
return _FeatureGates.EvaluationReason; | ||
return _types.EvaluationReason; | ||
} | ||
@@ -33,2 +33,8 @@ }); | ||
}); | ||
Object.defineProperty(exports, "Layer", { | ||
enumerable: true, | ||
get: function get() { | ||
return _Layer.Layer; | ||
} | ||
}); | ||
Object.defineProperty(exports, "PerimeterType", { | ||
@@ -47,3 +53,6 @@ enumerable: true, | ||
var _FeatureGates = _interopRequireWildcard(require("./client/FeatureGates")); | ||
var _DynamicConfig = require("./client/compat/DynamicConfig"); | ||
var _Layer = require("./client/compat/Layer"); | ||
var _types = require("./client/compat/types"); | ||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } | ||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } |
import _defineProperty from "@babel/runtime/helpers/defineProperty"; | ||
import Statsig, { DynamicConfig, EvaluationReason, Layer } from 'statsig-js-lite'; | ||
import { _makeLayer, StatsigClient } from '@statsig/js-client'; | ||
import Subscriptions from '../subscriptions'; | ||
import { DynamicConfig } from './compat/DynamicConfig'; | ||
import { Layer } from './compat/Layer'; | ||
import { EvaluationReason } from './compat/types'; | ||
import Fetcher from './fetcher'; | ||
import { NoFetchDataAdapter } from './NoFetchDataAdapter'; | ||
import { PersistentOverrideAdapter } from './PersistentOverrideAdapter'; | ||
import { FeatureGateEnvironment, PerimeterType } from './types'; | ||
import { getOptionsWithDefaults, shallowEquals, toStatsigOptions, toStatsigUser } from './utils'; | ||
import { getOptionsWithDefaults, migrateInitializationOptions, shallowEquals, toStatsigUser } from './utils'; | ||
import { CLIENT_VERSION } from './version'; | ||
const DEFAULT_CLIENT_KEY = 'client-default-key'; | ||
// default event logging api is Atlassian proxy rather than Statsig's domain, to avoid ad blockers | ||
const DEFAULT_EVENT_LOGGING_API = 'https://xp.atlassian.com/v1/'; | ||
const DEFAULT_EVENT_LOGGING_API = 'https://xp.atlassian.com/v1/rgstr'; | ||
export class Client { | ||
@@ -28,2 +33,17 @@ constructor() { | ||
_defineProperty(this, "subscriptions", new Subscriptions()); | ||
_defineProperty(this, "dataAdapter", new NoFetchDataAdapter()); | ||
_defineProperty(this, "overrideAdapter", new PersistentOverrideAdapter()); | ||
/** | ||
* Call this if modifying the values being served by the Statsig library since it has its own | ||
* memoization cache which will not be updated if the values are changed outside of the library. | ||
*/ | ||
_defineProperty(this, "statsigValuesUpdated", () => { | ||
if (this.user) { | ||
// Trigger a reset of the memoize cache | ||
this.statsigClient.updateUserSync(this.user, { | ||
disableBackgroundCacheRefresh: true | ||
}); | ||
} | ||
this.subscriptions.anyUpdated(); | ||
}); | ||
} | ||
@@ -114,4 +134,6 @@ /** | ||
if (this.initCompleted || this.initWithDefaults) { | ||
Statsig.setInitializeValues(experimentsResult.experimentValues); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.dataAdapter.setBootstrapData(experimentsResult.experimentValues); | ||
this.dataAdapter.setData(JSON.stringify(experimentsResult.experimentValues)); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -159,2 +181,8 @@ } catch (error) { | ||
} | ||
// This makes sure the new Statsig client behaves like the old when bootstrap data is | ||
// passed, and `has_updates` isn't specified (which happens a lot in product integration tests). | ||
if (!Object.prototype.hasOwnProperty.call(initializeValues, 'has_updates')) { | ||
initializeValues['has_updates'] = true; | ||
} | ||
const startTime = performance.now(); | ||
@@ -172,2 +200,7 @@ this.initOptions = clientOptionsWithDefaults; | ||
} | ||
assertInitialized(statsigClient) { | ||
if (!statsigClient) { | ||
throw new Error('Client must be initialized before using this method'); | ||
} | ||
} | ||
@@ -181,2 +214,3 @@ /** | ||
async updateUser(fetchOptions, identifiers, customAttributes) { | ||
this.assertInitialized(this.statsigClient); | ||
const fetchOptionsWithDefaults = getOptionsWithDefaults(fetchOptions); | ||
@@ -200,2 +234,3 @@ const initializeValuesProducer = () => Fetcher.fetchExperimentValues(fetchOptionsWithDefaults, identifiers, customAttributes).then(({ | ||
async updateUserWithProvider(identifiers, customAttributes) { | ||
this.assertInitialized(this.statsigClient); | ||
if (!this.provider) { | ||
@@ -217,2 +252,3 @@ throw new Error('Cannot update user using provider as the client was not initialised with a provider'); | ||
async updateUserWithValues(identifiers, customAttributes, initializeValues = {}) { | ||
this.assertInitialized(this.statsigClient); | ||
const initializeValuesProducer = () => Promise.resolve({ | ||
@@ -242,7 +278,9 @@ experimentValues: initializeValues, | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
const { | ||
fireGateExposure = true | ||
} = options; | ||
const evalMethod = fireGateExposure ? Statsig.checkGate.bind(Statsig) : Statsig.checkGateWithExposureLoggingDisabled.bind(Statsig); | ||
return evalMethod(gateName); | ||
return this.statsigClient.checkGate(gateName, { | ||
disableExposureLog: !fireGateExposure | ||
}); | ||
} catch (error) { | ||
@@ -264,5 +302,7 @@ // Log the first occurrence of the error | ||
try { | ||
// @ts-expect-error TS2341: Property _getClientX is private and only accessible within class Statsi | ||
const gate = Statsig._getClientX()._getGateFromStore(gateName); | ||
return gate.evaluationDetails.reason !== EvaluationReason.Unrecognized; | ||
this.assertInitialized(this.statsigClient); | ||
const gate = this.statsigClient.getFeatureGate(gateName, { | ||
disableExposureLog: true | ||
}); | ||
return !gate.details.reason.includes('Unrecognized'); | ||
} catch (error) { | ||
@@ -277,4 +317,7 @@ // eslint-disable-next-line no-console | ||
try { | ||
const config = Statsig.getExperimentWithExposureLoggingDisabled(experimentName); | ||
return config._evaluationDetails.reason !== EvaluationReason.Unrecognized; | ||
this.assertInitialized(this.statsigClient); | ||
const config = this.statsigClient.getExperiment(experimentName, { | ||
disableExposureLog: true | ||
}); | ||
return !config.details.reason.includes('Unrecognized'); | ||
} catch (error) { | ||
@@ -295,3 +338,6 @@ // eslint-disable-next-line no-console | ||
manuallyLogGateExposure(gateName) { | ||
Statsig.manuallyLogGateExposure(gateName); | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
this.statsigClient.checkGate(gateName); | ||
} | ||
@@ -316,7 +362,9 @@ | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
const { | ||
fireExperimentExposure = true | ||
} = options; | ||
const evalMethod = fireExperimentExposure ? Statsig.getExperiment.bind(Statsig) : Statsig.getExperimentWithExposureLoggingDisabled.bind(Statsig); | ||
return evalMethod(experimentName); | ||
return DynamicConfig.fromExperiment(this.statsigClient.getExperiment(experimentName, { | ||
disableExposureLog: !fireExperimentExposure | ||
})); | ||
} catch (error) { | ||
@@ -408,3 +456,6 @@ // Log the first occurrence of the error | ||
manuallyLogExperimentExposure(experimentName) { | ||
Statsig.manuallyLogExperimentExposure(experimentName); | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
this.statsigClient.getExperiment(experimentName); | ||
} | ||
@@ -419,6 +470,11 @@ | ||
manuallyLogLayerExposure(layerName, parameterName) { | ||
Statsig.manuallyLogLayerParameterExposure(layerName, parameterName); | ||
var _this$statsigClient$g; | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
(_this$statsigClient$g = this.statsigClient.getLayer(layerName)) === null || _this$statsigClient$g === void 0 ? void 0 : _this$statsigClient$g.get(parameterName); | ||
} | ||
shutdownStatsig() { | ||
Statsig.shutdown(); | ||
this.assertInitialized(this.statsigClient); | ||
this.statsigClient.shutdown(); | ||
} | ||
@@ -432,3 +488,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -443,4 +499,11 @@ * is called. If you are using this API for testing purposes, you should call | ||
overrideGate(gateName, value) { | ||
Statsig.overrideGate(gateName, value); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.overrideGate(gateName, value); | ||
// Trigger a reset of the memoized gate value | ||
if (this.user) { | ||
this.statsigClient.updateUserSync(this.user, { | ||
disableBackgroundCacheRefresh: true | ||
}); | ||
} | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -452,4 +515,5 @@ | ||
clearGateOverride(gateName) { | ||
Statsig.overrideGate(gateName, null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeGateOverride(gateName); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -463,3 +527,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -474,4 +538,5 @@ * is called. If you are using this API for testing purposes, you should call | ||
overrideConfig(experimentName, values) { | ||
Statsig.overrideConfig(experimentName, values); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.overrideDynamicConfig(experimentName, values); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -484,4 +549,5 @@ | ||
clearConfigOverride(experimentName) { | ||
Statsig.overrideConfig(experimentName, null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeDynamicConfigOverride(experimentName); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -496,3 +562,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -504,9 +570,5 @@ * is called. If you are using this API for testing purposes, you should call | ||
setOverrides(overrides) { | ||
Statsig.setOverrides({ | ||
gates: {}, | ||
configs: {}, | ||
layers: {}, | ||
...overrides | ||
}); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.setOverrides(overrides); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -518,3 +580,4 @@ | ||
getOverrides() { | ||
return Statsig.getOverrides(); | ||
this.assertInitialized(this.statsigClient); | ||
return this.overrideAdapter.getOverrides(); | ||
} | ||
@@ -526,4 +589,5 @@ | ||
clearAllOverrides() { | ||
Statsig.setOverrides(null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeAllOverrides(); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -596,3 +660,3 @@ | ||
}; | ||
return this.subscriptions.onExperimentValueUpdated(experimentName, parameterName, defaultValue, wrapCallback, this.getExperimentValue, options); | ||
return this.subscriptions.onExperimentValueUpdated(experimentName, parameterName, defaultValue, wrapCallback, this.getExperimentValue.bind(this), options); | ||
} | ||
@@ -695,21 +759,41 @@ | ||
async initFromValues(clientOptions, identifiers, customAttributes, initializeValues = {}) { | ||
const user = toStatsigUser(identifiers, customAttributes); | ||
var _newClientOptions$net; | ||
this.overrideAdapter.initFromStoredOverrides(); | ||
this.user = toStatsigUser(identifiers, customAttributes); | ||
this.currentIdentifiers = identifiers; | ||
this.currentAttributes = customAttributes; | ||
if (!clientOptions.sdkKey) { | ||
clientOptions.sdkKey = DEFAULT_CLIENT_KEY; | ||
const newClientOptions = migrateInitializationOptions(clientOptions); | ||
if (!newClientOptions.sdkKey) { | ||
newClientOptions.sdkKey = DEFAULT_CLIENT_KEY; | ||
} | ||
if (!clientOptions.eventLoggingApi) { | ||
clientOptions.eventLoggingApi = DEFAULT_EVENT_LOGGING_API; | ||
if (!((_newClientOptions$net = newClientOptions.networkConfig) !== null && _newClientOptions$net !== void 0 && _newClientOptions$net.logEventUrl)) { | ||
newClientOptions.networkConfig = { | ||
...newClientOptions.networkConfig, | ||
logEventUrl: DEFAULT_EVENT_LOGGING_API | ||
}; | ||
} | ||
if (clientOptions.perimeter === PerimeterType.FEDRAMP_MODERATE) { | ||
if (newClientOptions.perimeter === PerimeterType.FEDRAMP_MODERATE) { | ||
// disable all logging in FedRAMP to prevent egress of sensitive data | ||
clientOptions.disableAllLogging = true; | ||
newClientOptions.disableLogging = true; | ||
} | ||
const { | ||
sdkKey | ||
} = clientOptions; | ||
const statsigOptions = toStatsigOptions(clientOptions, initializeValues); | ||
sdkKey, | ||
environment, | ||
updateUserCompletionCallback: _updateUserCompletionCallback, | ||
perimeter: _perimeter, | ||
...restClientOptions | ||
} = newClientOptions; | ||
const statsigOptions = { | ||
...restClientOptions, | ||
environment: { | ||
tier: environment | ||
}, | ||
includeCurrentPageUrlWithEvents: false, | ||
dataAdapter: this.dataAdapter, | ||
overrideAdapter: this.overrideAdapter | ||
}; | ||
try { | ||
await Statsig.initialize(sdkKey, user, statsigOptions); | ||
this.statsigClient = new StatsigClient(sdkKey, this.user, statsigOptions); | ||
this.dataAdapter.setBootstrapData(initializeValues); | ||
await this.statsigClient.initializeAsync(); | ||
} catch (error) { | ||
@@ -722,6 +806,5 @@ if (error instanceof Error) { | ||
console.warn(`Initialising Statsig client with default sdk key and without values`); | ||
await Statsig.initialize(DEFAULT_CLIENT_KEY, user, { | ||
...statsigOptions, | ||
initializeValues: {} | ||
}); | ||
this.statsigClient = new StatsigClient(DEFAULT_CLIENT_KEY, this.user, statsigOptions); | ||
this.dataAdapter.setBootstrapData(); | ||
await this.statsigClient.initializeAsync(); | ||
this.initWithDefaults = true; | ||
@@ -744,2 +827,3 @@ throw error; | ||
async updateUserUsingInitializeValuesProducer(getInitializeValues, identifiers, customAttributes) { | ||
this.assertInitialized(this.statsigClient); | ||
if (!this.initPromise) { | ||
@@ -789,2 +873,4 @@ throw new Error('The client must be initialized before you can update the user.'); | ||
async updateStatsigClientUser(initializeValuesPromise, identifiers, customAttributes) { | ||
var _this$initOptions, _this$initOptions$upd; | ||
this.assertInitialized(this.statsigClient); | ||
let initializeValues, user; | ||
@@ -803,3 +889,13 @@ try { | ||
} | ||
const success = Statsig.updateUserWithValues(user, initializeValues.experimentValues); | ||
let success = true; | ||
let errorMessage = null; | ||
try { | ||
this.dataAdapter.setBootstrapData(initializeValues.experimentValues); | ||
this.user = user; | ||
await this.statsigClient.updateUserAsync(this.user); | ||
} catch (err) { | ||
success = false; | ||
errorMessage = String(err); | ||
} | ||
(_this$initOptions = this.initOptions) === null || _this$initOptions === void 0 ? void 0 : (_this$initOptions$upd = _this$initOptions.updateUserCompletionCallback) === null || _this$initOptions$upd === void 0 ? void 0 : _this$initOptions$upd.call(_this$initOptions, success, errorMessage); | ||
if (success) { | ||
@@ -813,3 +909,2 @@ this.currentIdentifiers = identifiers; | ||
} | ||
/** | ||
@@ -840,7 +935,9 @@ * @returns string version of the current package in semver style. | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
const { | ||
fireLayerExposure = true | ||
} = options; | ||
const evalMethod = fireLayerExposure ? Statsig.getLayer.bind(Statsig) : Statsig.getLayerWithExposureLoggingDisabled.bind(Statsig); | ||
return evalMethod(layerName); | ||
return Layer.fromLayer(this.statsigClient.getLayer(layerName, { | ||
disableExposureLog: !fireLayerExposure | ||
})); | ||
} catch (error) { | ||
@@ -859,6 +956,5 @@ // Log the first occurrence of the error | ||
// Return a default value | ||
return Layer._create(layerName, {}, '', { | ||
time: Date.now(), | ||
reason: EvaluationReason.Error | ||
}); | ||
return Layer.fromLayer(_makeLayer(layerName, { | ||
reason: 'Error' | ||
}, null)); | ||
} | ||
@@ -865,0 +961,0 @@ } |
@@ -5,3 +5,4 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty"; | ||
import { CLIENT_VERSION } from './version'; | ||
export { DynamicConfig, EvaluationReason } from 'statsig-js-lite'; | ||
export { EvaluationReason } from './compat/types'; | ||
export { DynamicConfig } from './compat/DynamicConfig'; | ||
export { FeatureGateEnvironment, PerimeterType } from './types'; | ||
@@ -65,17 +66,14 @@ export { CLIENT_VERSION } from './version'; | ||
// Log the first occurrence of the error | ||
if (!_FeatureGates.hasCheckGateErrorOccurred) { | ||
// Log the first occurrence of the error | ||
if (!_FeatureGates.hasGetExperimentValueErrorOccurred) { | ||
// eslint-disable-next-line no-console | ||
console.warn({ | ||
msg: 'An error has occurred getting the experiment value from criterion override. Only the first occurrence of this error is logged.', | ||
experimentName, | ||
defaultValue, | ||
options, | ||
error | ||
}); | ||
_FeatureGates.hasGetExperimentValueErrorOccurred = true; | ||
} | ||
return defaultValue; | ||
if (!_FeatureGates.hasGetExperimentValueErrorOccurred) { | ||
// eslint-disable-next-line no-console | ||
console.warn({ | ||
msg: 'An error has occurred getting the experiment value from criterion override. Only the first occurrence of this error is logged.', | ||
experimentName, | ||
defaultValue, | ||
options, | ||
error | ||
}); | ||
_FeatureGates.hasGetExperimentValueErrorOccurred = true; | ||
} | ||
return defaultValue; | ||
} | ||
@@ -82,0 +80,0 @@ |
import { isFedRamp } from '@atlaskit/atlassian-context'; | ||
import { EvaluationReason } from './compat/types'; | ||
import { PerimeterType } from './types'; | ||
@@ -50,46 +51,48 @@ export const getOptionsWithDefaults = options => ({ | ||
}; | ||
/** | ||
* This method transforms the options given by the user into the format accepted by the Statsig | ||
* client. | ||
*/ | ||
export const toStatsigOptions = (options, initializeValues) => { | ||
export const migrateInitializationOptions = options => { | ||
const { | ||
// De-structured to remove from restClientOptions | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
sdkKey, | ||
// De-structured to remove from restClientOptions | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
updateUserCompletionCallback, | ||
// De-structured to remove from restClientOptions | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
perimeter, | ||
...restClientOptions | ||
api, | ||
disableCurrentPageLogging, | ||
loggingIntervalMillis, | ||
loggingBufferMaxSize, | ||
localMode, | ||
eventLoggingApi, | ||
eventLoggingApiForRetries, | ||
disableLocalStorage, | ||
ignoreWindowUndefined, | ||
disableAllLogging, | ||
// No equivalent but is pointless anyway since our Statsig init is synchronous | ||
initTimeoutMs: _initTimeoutMs, | ||
// No equivalent in new client but probably not important? | ||
disableNetworkKeepalive: _disableNetworkKeepalive, | ||
// Needs to be implemented manually but unused according to zoekt | ||
overrideStableID: _overrideStableID, | ||
// No equivalent for these but can't see them actually used anywhere in old client? | ||
disableErrorLogging: _disableErrorLogging, | ||
disableAutoMetricsLogging: _disableAutoMetricsLogging, | ||
...rest | ||
} = options; | ||
return { | ||
...restClientOptions, | ||
initializeValues, | ||
environment: { | ||
tier: options.environment | ||
...rest, | ||
networkConfig: { | ||
api, | ||
logEventUrl: eventLoggingApi ? eventLoggingApi + 'rgstr' : undefined, | ||
logEventFallbackUrls: eventLoggingApiForRetries ? [eventLoggingApiForRetries] : undefined, | ||
preventAllNetworkTraffic: localMode || !ignoreWindowUndefined && typeof window === 'undefined' | ||
}, | ||
disableCurrentPageLogging: true, | ||
...(options.updateUserCompletionCallback && { | ||
updateUserCompletionCallback: toStatsigUpdateUserCompletionCallback(options.updateUserCompletionCallback) | ||
}) | ||
includeCurrentPageUrlWithEvents: !disableCurrentPageLogging, | ||
loggingIntervalMs: loggingIntervalMillis, | ||
loggingBufferMaxSize, | ||
disableStorage: disableLocalStorage, | ||
disableLogging: disableAllLogging | ||
}; | ||
}; | ||
/** | ||
* This method transforms an UpdateUserCompletionCallback in our own format into the format | ||
* accepted by the Statsig client. | ||
*/ | ||
export const toStatsigUpdateUserCompletionCallback = callback => { | ||
/** | ||
* The duration passed to the callback indicates how long the update took, but it is deceptive | ||
* since it only times the Statsig code and doesn't account for all of the extra custom work we | ||
* do to obtain the bootstrap values. As a result, we just suppress this parameter in our own | ||
* callback rather than trying to keep it accurate. | ||
*/ | ||
return (_duration, success, message) => { | ||
callback(success, message); | ||
const evaluationReasonMappings = Object.entries(EvaluationReason).map(([key, value]) => [key.toLowerCase(), value]); | ||
export const migrateEvaluationDetails = details => { | ||
var _evaluationReasonMapp, _evaluationReasonMapp2, _details$receivedAt; | ||
const reasonLower = details.reason.toLowerCase(); | ||
return { | ||
reason: (_evaluationReasonMapp = (_evaluationReasonMapp2 = evaluationReasonMappings.find(([key]) => reasonLower.includes(key))) === null || _evaluationReasonMapp2 === void 0 ? void 0 : _evaluationReasonMapp2[1]) !== null && _evaluationReasonMapp !== void 0 ? _evaluationReasonMapp : EvaluationReason.Unknown, | ||
time: (_details$receivedAt = details.receivedAt) !== null && _details$receivedAt !== void 0 ? _details$receivedAt : Date.now() | ||
}; | ||
}; |
/// <reference types="node" /> | ||
export const CLIENT_VERSION = "4.23.4"; | ||
export const CLIENT_VERSION = "4.24.0"; |
@@ -1,3 +0,4 @@ | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION, | ||
// Statsig | ||
DynamicConfig, EvaluationReason } from './client/FeatureGates'; | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION } from './client/FeatureGates'; | ||
export { DynamicConfig } from './client/compat/DynamicConfig'; | ||
export { Layer } from './client/compat/Layer'; | ||
export { EvaluationReason } from './client/compat/types'; |
@@ -0,1 +1,2 @@ | ||
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; | ||
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; | ||
@@ -6,16 +7,23 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; | ||
import _defineProperty from "@babel/runtime/helpers/defineProperty"; | ||
var _excluded = ["sdkKey", "environment", "updateUserCompletionCallback", "perimeter"]; | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
import _regeneratorRuntime from "@babel/runtime/regenerator"; | ||
import Statsig, { DynamicConfig, EvaluationReason, Layer } from 'statsig-js-lite'; | ||
import { _makeLayer, StatsigClient } from '@statsig/js-client'; | ||
import Subscriptions from '../subscriptions'; | ||
import { DynamicConfig } from './compat/DynamicConfig'; | ||
import { Layer } from './compat/Layer'; | ||
import { EvaluationReason } from './compat/types'; | ||
import Fetcher from './fetcher'; | ||
import { NoFetchDataAdapter } from './NoFetchDataAdapter'; | ||
import { PersistentOverrideAdapter } from './PersistentOverrideAdapter'; | ||
import { FeatureGateEnvironment, PerimeterType } from './types'; | ||
import { getOptionsWithDefaults, shallowEquals, toStatsigOptions, toStatsigUser } from './utils'; | ||
import { getOptionsWithDefaults, migrateInitializationOptions, shallowEquals, toStatsigUser } from './utils'; | ||
import { CLIENT_VERSION } from './version'; | ||
var DEFAULT_CLIENT_KEY = 'client-default-key'; | ||
// default event logging api is Atlassian proxy rather than Statsig's domain, to avoid ad blockers | ||
var DEFAULT_EVENT_LOGGING_API = 'https://xp.atlassian.com/v1/'; | ||
var DEFAULT_EVENT_LOGGING_API = 'https://xp.atlassian.com/v1/rgstr'; | ||
export var Client = /*#__PURE__*/function () { | ||
function Client() { | ||
var _this = this; | ||
_classCallCheck(this, Client); | ||
@@ -37,2 +45,17 @@ _defineProperty(this, "initPromise", null); | ||
_defineProperty(this, "subscriptions", new Subscriptions()); | ||
_defineProperty(this, "dataAdapter", new NoFetchDataAdapter()); | ||
_defineProperty(this, "overrideAdapter", new PersistentOverrideAdapter()); | ||
/** | ||
* Call this if modifying the values being served by the Statsig library since it has its own | ||
* memoization cache which will not be updated if the values are changed outside of the library. | ||
*/ | ||
_defineProperty(this, "statsigValuesUpdated", function () { | ||
if (_this.user) { | ||
// Trigger a reset of the memoize cache | ||
_this.statsigClient.updateUserSync(_this.user, { | ||
disableBackgroundCacheRefresh: true | ||
}); | ||
} | ||
_this.subscriptions.anyUpdated(); | ||
}); | ||
} | ||
@@ -60,3 +83,3 @@ return _createClass(Client, [{ | ||
var _initialize = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(clientOptions, identifiers, customAttributes) { | ||
var _this = this; | ||
var _this2 = this; | ||
var clientOptionsWithDefaults, startTime; | ||
@@ -80,8 +103,8 @@ return _regeneratorRuntime.wrap(function _callee$(_context) { | ||
this.initPromise = this.init(clientOptionsWithDefaults, identifiers, customAttributes).then(function () { | ||
_this.initCompleted = true; | ||
_this.initWithDefaults = true; | ||
_this2.initCompleted = true; | ||
_this2.initWithDefaults = true; | ||
}).finally(function () { | ||
var endTime = performance.now(); | ||
var totalTime = endTime - startTime; | ||
_this.fireClientEvent(startTime, totalTime, 'initialize', _this.initCompleted, clientOptionsWithDefaults.apiKey); | ||
_this2.fireClientEvent(startTime, totalTime, 'initialize', _this2.initCompleted, clientOptionsWithDefaults.apiKey); | ||
}); | ||
@@ -122,3 +145,3 @@ return _context.abrupt("return", this.initPromise); | ||
var _initializeWithProvider = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(clientOptions, provider, identifiers, customAttributes) { | ||
var _this2 = this; | ||
var _this3 = this; | ||
var clientOptionsWithDefaults, startTime; | ||
@@ -147,8 +170,8 @@ return _regeneratorRuntime.wrap(function _callee2$(_context2) { | ||
this.initPromise = this.initWithProvider(clientOptionsWithDefaults, provider, identifiers, customAttributes).then(function () { | ||
_this2.initCompleted = true; | ||
_this2.initWithDefaults = true; | ||
_this3.initCompleted = true; | ||
_this3.initWithDefaults = true; | ||
}).finally(function () { | ||
var endTime = performance.now(); | ||
var totalTime = endTime - startTime; | ||
_this2.fireClientEvent(startTime, totalTime, 'initializeWithProvider', _this2.initCompleted, provider.getApiKey ? provider.getApiKey() : undefined); | ||
_this3.fireClientEvent(startTime, totalTime, 'initializeWithProvider', _this3.initCompleted, provider.getApiKey ? provider.getApiKey() : undefined); | ||
}); | ||
@@ -172,4 +195,6 @@ return _context2.abrupt("return", this.initPromise); | ||
if (this.initCompleted || this.initWithDefaults) { | ||
Statsig.setInitializeValues(experimentsResult.experimentValues); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.dataAdapter.setBootstrapData(experimentsResult.experimentValues); | ||
this.dataAdapter.setData(JSON.stringify(experimentsResult.experimentValues)); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -185,7 +210,7 @@ } catch (error) { | ||
var _analyticsWebClient, | ||
_this3 = this; | ||
_this4 = this; | ||
var apiKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; | ||
(_analyticsWebClient = this.initOptions.analyticsWebClient) === null || _analyticsWebClient === void 0 || _analyticsWebClient.then(function (analyticsWebClient) { | ||
var attributes = _objectSpread({ | ||
targetApp: _this3.initOptions.targetApp, | ||
targetApp: _this4.initOptions.targetApp, | ||
clientVersion: CLIENT_VERSION, | ||
@@ -206,3 +231,3 @@ success: success, | ||
}).catch(function (err) { | ||
if (_this3.initOptions.environment !== FeatureGateEnvironment.Production) { | ||
if (_this4.initOptions.environment !== FeatureGateEnvironment.Production) { | ||
// eslint-disable-next-line no-console | ||
@@ -217,3 +242,3 @@ console.error('Analytics web client promise did not resolve', err); | ||
var _initializeFromValues = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(clientOptions, identifiers, customAttributes) { | ||
var _this4 = this; | ||
var _this5 = this; | ||
var initializeValues, | ||
@@ -238,14 +263,19 @@ clientOptionsWithDefaults, | ||
case 5: | ||
// This makes sure the new Statsig client behaves like the old when bootstrap data is | ||
// passed, and `has_updates` isn't specified (which happens a lot in product integration tests). | ||
if (!Object.prototype.hasOwnProperty.call(initializeValues, 'has_updates')) { | ||
initializeValues['has_updates'] = true; | ||
} | ||
startTime = performance.now(); | ||
this.initOptions = clientOptionsWithDefaults; | ||
this.initPromise = this.initFromValues(clientOptionsWithDefaults, identifiers, customAttributes, initializeValues).then(function () { | ||
_this4.initCompleted = true; | ||
_this4.initWithDefaults = true; | ||
_this5.initCompleted = true; | ||
_this5.initWithDefaults = true; | ||
}).finally(function () { | ||
var endTime = performance.now(); | ||
var totalTime = endTime - startTime; | ||
_this4.fireClientEvent(startTime, totalTime, 'initializeFromValues', _this4.initCompleted); | ||
_this5.fireClientEvent(startTime, totalTime, 'initializeFromValues', _this5.initCompleted); | ||
}); | ||
return _context3.abrupt("return", this.initPromise); | ||
case 9: | ||
case 10: | ||
case "end": | ||
@@ -261,2 +291,10 @@ return _context3.stop(); | ||
}() | ||
}, { | ||
key: "assertInitialized", | ||
value: function assertInitialized(statsigClient) { | ||
if (!statsigClient) { | ||
throw new Error('Client must be initialized before using this method'); | ||
} | ||
} | ||
/** | ||
@@ -276,2 +314,3 @@ * This method updates the user using a network call to fetch the new set of values. | ||
case 0: | ||
this.assertInitialized(this.statsigClient); | ||
fetchOptionsWithDefaults = getOptionsWithDefaults(fetchOptions); | ||
@@ -288,5 +327,5 @@ initializeValuesProducer = function initializeValuesProducer() { | ||
}; | ||
_context4.next = 4; | ||
_context4.next = 5; | ||
return this.updateUserUsingInitializeValuesProducer(initializeValuesProducer, identifiers, customAttributes); | ||
case 4: | ||
case 5: | ||
case "end": | ||
@@ -313,20 +352,21 @@ return _context4.stop(); | ||
var _updateUserWithProvider = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(identifiers, customAttributes) { | ||
var _this5 = this; | ||
var _this6 = this; | ||
return _regeneratorRuntime.wrap(function _callee5$(_context5) { | ||
while (1) switch (_context5.prev = _context5.next) { | ||
case 0: | ||
this.assertInitialized(this.statsigClient); | ||
if (this.provider) { | ||
_context5.next = 2; | ||
_context5.next = 3; | ||
break; | ||
} | ||
throw new Error('Cannot update user using provider as the client was not initialised with a provider'); | ||
case 2: | ||
_context5.next = 4; | ||
case 3: | ||
_context5.next = 5; | ||
return this.provider.setProfile(this.initOptions, identifiers, customAttributes); | ||
case 4: | ||
_context5.next = 6; | ||
case 5: | ||
_context5.next = 7; | ||
return this.updateUserUsingInitializeValuesProducer(function () { | ||
return _this5.provider.getExperimentValues(); | ||
return _this6.provider.getExperimentValues(); | ||
}, identifiers, customAttributes); | ||
case 6: | ||
case 7: | ||
case "end": | ||
@@ -362,2 +402,3 @@ return _context5.stop(); | ||
initializeValues = _args6.length > 2 && _args6[2] !== undefined ? _args6[2] : {}; | ||
this.assertInitialized(this.statsigClient); | ||
initializeValuesProducer = function initializeValuesProducer() { | ||
@@ -369,5 +410,5 @@ return Promise.resolve({ | ||
}; | ||
_context6.next = 4; | ||
_context6.next = 5; | ||
return this.updateUserUsingInitializeValuesProducer(initializeValuesProducer, identifiers, customAttributes); | ||
case 4: | ||
case 5: | ||
case "end": | ||
@@ -408,6 +449,8 @@ return _context6.stop(); | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
var _options$fireGateExpo = options.fireGateExposure, | ||
fireGateExposure = _options$fireGateExpo === void 0 ? true : _options$fireGateExpo; | ||
var evalMethod = fireGateExposure ? Statsig.checkGate.bind(Statsig) : Statsig.checkGateWithExposureLoggingDisabled.bind(Statsig); | ||
return evalMethod(gateName); | ||
return this.statsigClient.checkGate(gateName, { | ||
disableExposureLog: !fireGateExposure | ||
}); | ||
} catch (error) { | ||
@@ -431,5 +474,7 @@ // Log the first occurrence of the error | ||
try { | ||
// @ts-expect-error TS2341: Property _getClientX is private and only accessible within class Statsi | ||
var gate = Statsig._getClientX()._getGateFromStore(gateName); | ||
return gate.evaluationDetails.reason !== EvaluationReason.Unrecognized; | ||
this.assertInitialized(this.statsigClient); | ||
var gate = this.statsigClient.getFeatureGate(gateName, { | ||
disableExposureLog: true | ||
}); | ||
return !gate.details.reason.includes('Unrecognized'); | ||
} catch (error) { | ||
@@ -446,4 +491,7 @@ // eslint-disable-next-line no-console | ||
try { | ||
var config = Statsig.getExperimentWithExposureLoggingDisabled(experimentName); | ||
return config._evaluationDetails.reason !== EvaluationReason.Unrecognized; | ||
this.assertInitialized(this.statsigClient); | ||
var config = this.statsigClient.getExperiment(experimentName, { | ||
disableExposureLog: true | ||
}); | ||
return !config.details.reason.includes('Unrecognized'); | ||
} catch (error) { | ||
@@ -466,3 +514,6 @@ // eslint-disable-next-line no-console | ||
value: function manuallyLogGateExposure(gateName) { | ||
Statsig.manuallyLogGateExposure(gateName); | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
this.statsigClient.checkGate(gateName); | ||
} | ||
@@ -490,6 +541,8 @@ | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
var _options$fireExperime = options.fireExperimentExposure, | ||
fireExperimentExposure = _options$fireExperime === void 0 ? true : _options$fireExperime; | ||
var evalMethod = fireExperimentExposure ? Statsig.getExperiment.bind(Statsig) : Statsig.getExperimentWithExposureLoggingDisabled.bind(Statsig); | ||
return evalMethod(experimentName); | ||
return DynamicConfig.fromExperiment(this.statsigClient.getExperiment(experimentName, { | ||
disableExposureLog: !fireExperimentExposure | ||
})); | ||
} catch (error) { | ||
@@ -584,3 +637,6 @@ // Log the first occurrence of the error | ||
value: function manuallyLogExperimentExposure(experimentName) { | ||
Statsig.manuallyLogExperimentExposure(experimentName); | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
this.statsigClient.getExperiment(experimentName); | ||
} | ||
@@ -597,3 +653,7 @@ | ||
value: function manuallyLogLayerExposure(layerName, parameterName) { | ||
Statsig.manuallyLogLayerParameterExposure(layerName, parameterName); | ||
var _this$statsigClient$g; | ||
this.assertInitialized(this.statsigClient); | ||
// This is the approach recommended in the docs | ||
// https://docs.statsig.com/client/javascript-sdk/#manual-exposures- | ||
(_this$statsigClient$g = this.statsigClient.getLayer(layerName)) === null || _this$statsigClient$g === void 0 || _this$statsigClient$g.get(parameterName); | ||
} | ||
@@ -603,3 +663,4 @@ }, { | ||
value: function shutdownStatsig() { | ||
Statsig.shutdown(); | ||
this.assertInitialized(this.statsigClient); | ||
this.statsigClient.shutdown(); | ||
} | ||
@@ -613,3 +674,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -626,4 +687,11 @@ * is called. If you are using this API for testing purposes, you should call | ||
value: function overrideGate(gateName, value) { | ||
Statsig.overrideGate(gateName, value); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.overrideGate(gateName, value); | ||
// Trigger a reset of the memoized gate value | ||
if (this.user) { | ||
this.statsigClient.updateUserSync(this.user, { | ||
disableBackgroundCacheRefresh: true | ||
}); | ||
} | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -637,4 +705,5 @@ | ||
value: function clearGateOverride(gateName) { | ||
Statsig.overrideGate(gateName, null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeGateOverride(gateName); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -648,3 +717,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -661,4 +730,5 @@ * is called. If you are using this API for testing purposes, you should call | ||
value: function overrideConfig(experimentName, values) { | ||
Statsig.overrideConfig(experimentName, values); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.overrideDynamicConfig(experimentName, values); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -673,4 +743,5 @@ | ||
value: function clearConfigOverride(experimentName) { | ||
Statsig.overrideConfig(experimentName, null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeDynamicConfigOverride(experimentName); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -685,3 +756,3 @@ | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -695,8 +766,5 @@ * is called. If you are using this API for testing purposes, you should call | ||
value: function setOverrides(overrides) { | ||
Statsig.setOverrides(_objectSpread({ | ||
gates: {}, | ||
configs: {}, | ||
layers: {} | ||
}, overrides)); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.setOverrides(overrides); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -710,3 +778,4 @@ | ||
value: function getOverrides() { | ||
return Statsig.getOverrides(); | ||
this.assertInitialized(this.statsigClient); | ||
return this.overrideAdapter.getOverrides(); | ||
} | ||
@@ -720,4 +789,5 @@ | ||
value: function clearAllOverrides() { | ||
Statsig.setOverrides(null); | ||
this.subscriptions.anyUpdated(); | ||
this.assertInitialized(this.statsigClient); | ||
this.overrideAdapter.removeAllOverrides(); | ||
this.statsigValuesUpdated(); | ||
} | ||
@@ -753,3 +823,3 @@ | ||
value: function onGateUpdated(gateName, callback) { | ||
var _this6 = this; | ||
var _this7 = this; | ||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
@@ -760,3 +830,3 @@ var wrapCallback = function wrapCallback(value) { | ||
if (fireGateExposure) { | ||
_this6.manuallyLogGateExposure(gateName); | ||
_this7.manuallyLogGateExposure(gateName); | ||
} | ||
@@ -785,3 +855,3 @@ try { | ||
value: function onExperimentValueUpdated(experimentName, parameterName, defaultValue, callback) { | ||
var _this7 = this; | ||
var _this8 = this; | ||
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; | ||
@@ -792,3 +862,3 @@ var wrapCallback = function wrapCallback(value) { | ||
if (fireExperimentExposure) { | ||
_this7.manuallyLogExperimentExposure(experimentName); | ||
_this8.manuallyLogExperimentExposure(experimentName); | ||
} | ||
@@ -802,3 +872,3 @@ try { | ||
}; | ||
return this.subscriptions.onExperimentValueUpdated(experimentName, parameterName, defaultValue, wrapCallback, this.getExperimentValue, options); | ||
return this.subscriptions.onExperimentValueUpdated(experimentName, parameterName, defaultValue, wrapCallback, this.getExperimentValue.bind(this), options); | ||
} | ||
@@ -955,5 +1025,10 @@ | ||
var _initFromValues = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(clientOptions, identifiers, customAttributes) { | ||
var _newClientOptions$net; | ||
var initializeValues, | ||
user, | ||
newClientOptions, | ||
sdkKey, | ||
environment, | ||
_updateUserCompletionCallback, | ||
_perimeter, | ||
restClientOptions, | ||
statsigOptions, | ||
@@ -965,26 +1040,39 @@ _args9 = arguments; | ||
initializeValues = _args9.length > 3 && _args9[3] !== undefined ? _args9[3] : {}; | ||
user = toStatsigUser(identifiers, customAttributes); | ||
this.overrideAdapter.initFromStoredOverrides(); | ||
this.user = toStatsigUser(identifiers, customAttributes); | ||
this.currentIdentifiers = identifiers; | ||
this.currentAttributes = customAttributes; | ||
if (!clientOptions.sdkKey) { | ||
clientOptions.sdkKey = DEFAULT_CLIENT_KEY; | ||
newClientOptions = migrateInitializationOptions(clientOptions); | ||
if (!newClientOptions.sdkKey) { | ||
newClientOptions.sdkKey = DEFAULT_CLIENT_KEY; | ||
} | ||
if (!clientOptions.eventLoggingApi) { | ||
clientOptions.eventLoggingApi = DEFAULT_EVENT_LOGGING_API; | ||
if (!((_newClientOptions$net = newClientOptions.networkConfig) !== null && _newClientOptions$net !== void 0 && _newClientOptions$net.logEventUrl)) { | ||
newClientOptions.networkConfig = _objectSpread(_objectSpread({}, newClientOptions.networkConfig), {}, { | ||
logEventUrl: DEFAULT_EVENT_LOGGING_API | ||
}); | ||
} | ||
if (clientOptions.perimeter === PerimeterType.FEDRAMP_MODERATE) { | ||
if (newClientOptions.perimeter === PerimeterType.FEDRAMP_MODERATE) { | ||
// disable all logging in FedRAMP to prevent egress of sensitive data | ||
clientOptions.disableAllLogging = true; | ||
newClientOptions.disableLogging = true; | ||
} | ||
sdkKey = clientOptions.sdkKey; | ||
statsigOptions = toStatsigOptions(clientOptions, initializeValues); | ||
_context9.prev = 9; | ||
_context9.next = 12; | ||
return Statsig.initialize(sdkKey, user, statsigOptions); | ||
case 12: | ||
_context9.next = 22; | ||
sdkKey = newClientOptions.sdkKey, environment = newClientOptions.environment, _updateUserCompletionCallback = newClientOptions.updateUserCompletionCallback, _perimeter = newClientOptions.perimeter, restClientOptions = _objectWithoutProperties(newClientOptions, _excluded); | ||
statsigOptions = _objectSpread(_objectSpread({}, restClientOptions), {}, { | ||
environment: { | ||
tier: environment | ||
}, | ||
includeCurrentPageUrlWithEvents: false, | ||
dataAdapter: this.dataAdapter, | ||
overrideAdapter: this.overrideAdapter | ||
}); | ||
_context9.prev = 11; | ||
this.statsigClient = new StatsigClient(sdkKey, this.user, statsigOptions); | ||
this.dataAdapter.setBootstrapData(initializeValues); | ||
_context9.next = 16; | ||
return this.statsigClient.initializeAsync(); | ||
case 16: | ||
_context9.next = 28; | ||
break; | ||
case 14: | ||
_context9.prev = 14; | ||
_context9.t0 = _context9["catch"](9); | ||
case 18: | ||
_context9.prev = 18; | ||
_context9.t0 = _context9["catch"](11); | ||
if (_context9.t0 instanceof Error) { | ||
@@ -996,14 +1084,14 @@ // eslint-disable-next-line no-console | ||
console.warn("Initialising Statsig client with default sdk key and without values"); | ||
_context9.next = 20; | ||
return Statsig.initialize(DEFAULT_CLIENT_KEY, user, _objectSpread(_objectSpread({}, statsigOptions), {}, { | ||
initializeValues: {} | ||
})); | ||
case 20: | ||
this.statsigClient = new StatsigClient(DEFAULT_CLIENT_KEY, this.user, statsigOptions); | ||
this.dataAdapter.setBootstrapData(); | ||
_context9.next = 26; | ||
return this.statsigClient.initializeAsync(); | ||
case 26: | ||
this.initWithDefaults = true; | ||
throw _context9.t0; | ||
case 22: | ||
case 28: | ||
case "end": | ||
return _context9.stop(); | ||
} | ||
}, _callee9, this, [[9, 14]]); | ||
}, _callee9, this, [[11, 18]]); | ||
})); | ||
@@ -1031,3 +1119,3 @@ function initFromValues(_x25, _x26, _x27) { | ||
var _updateUserUsingInitializeValuesProducer = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11(getInitializeValues, identifiers, customAttributes) { | ||
var _this8 = this; | ||
var _this9 = this; | ||
var originalInitPromise, initializeValuesPromise, updateUserPromise; | ||
@@ -1037,26 +1125,27 @@ return _regeneratorRuntime.wrap(function _callee11$(_context11) { | ||
case 0: | ||
this.assertInitialized(this.statsigClient); | ||
if (this.initPromise) { | ||
_context11.next = 2; | ||
_context11.next = 3; | ||
break; | ||
} | ||
throw new Error('The client must be initialized before you can update the user.'); | ||
case 2: | ||
case 3: | ||
if (!this.isCurrentUser(identifiers, customAttributes)) { | ||
_context11.next = 4; | ||
_context11.next = 5; | ||
break; | ||
} | ||
return _context11.abrupt("return", this.initPromise); | ||
case 4: | ||
case 5: | ||
// Wait for the current initialize/update to finish | ||
originalInitPromise = this.initPromise; | ||
_context11.prev = 5; | ||
_context11.next = 8; | ||
_context11.prev = 6; | ||
_context11.next = 9; | ||
return this.initPromise; | ||
case 8: | ||
_context11.next = 12; | ||
case 9: | ||
_context11.next = 13; | ||
break; | ||
case 10: | ||
_context11.prev = 10; | ||
_context11.t0 = _context11["catch"](5); | ||
case 12: | ||
case 11: | ||
_context11.prev = 11; | ||
_context11.t0 = _context11["catch"](6); | ||
case 13: | ||
initializeValuesPromise = getInitializeValues(); | ||
@@ -1071,6 +1160,6 @@ updateUserPromise = this.updateStatsigClientUser(initializeValuesPromise, identifiers, customAttributes); // We replace the init promise here since we are essentially re-initializing the client at this | ||
// If the update failed then it changed nothing, so revert back to the original promise. | ||
_this8.initPromise = originalInitPromise; | ||
_this9.initPromise = originalInitPromise; | ||
// Set the user profile again to revert back to the current user | ||
if (!_this8.provider) { | ||
if (!_this9.provider) { | ||
_context10.next = 4; | ||
@@ -1080,3 +1169,3 @@ break; | ||
_context10.next = 4; | ||
return _this8.provider.setProfile(_this8.initOptions, _this8.currentIdentifiers, _this8.currentAttributes); | ||
return _this9.provider.setProfile(_this9.initOptions, _this9.currentIdentifiers, _this9.currentAttributes); | ||
case 4: | ||
@@ -1089,7 +1178,7 @@ case "end": | ||
return _context11.abrupt("return", updateUserPromise); | ||
case 16: | ||
case 17: | ||
case "end": | ||
return _context11.stop(); | ||
} | ||
}, _callee11, this, [[5, 10]]); | ||
}, _callee11, this, [[6, 11]]); | ||
})); | ||
@@ -1114,17 +1203,19 @@ function updateUserUsingInitializeValuesProducer(_x28, _x29, _x30) { | ||
var _updateStatsigClientUser = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12(initializeValuesPromise, identifiers, customAttributes) { | ||
var initializeValues, user, _updateUserCompletion, _ref3, errMsg, success; | ||
var _this$initOptions, _this$initOptions$upd; | ||
var initializeValues, user, _updateUserCompletion, _ref3, errMsg, success, errorMessage; | ||
return _regeneratorRuntime.wrap(function _callee12$(_context12) { | ||
while (1) switch (_context12.prev = _context12.next) { | ||
case 0: | ||
_context12.prev = 0; | ||
_context12.next = 3; | ||
this.assertInitialized(this.statsigClient); | ||
_context12.prev = 1; | ||
_context12.next = 4; | ||
return initializeValuesPromise; | ||
case 3: | ||
case 4: | ||
initializeValues = _context12.sent; | ||
user = toStatsigUser(identifiers, initializeValues.customAttributesFromFetch); | ||
_context12.next = 12; | ||
_context12.next = 13; | ||
break; | ||
case 7: | ||
_context12.prev = 7; | ||
_context12.t0 = _context12["catch"](0); | ||
case 8: | ||
_context12.prev = 8; | ||
_context12.t0 = _context12["catch"](1); | ||
// Make sure the updateUserCompletionCallback is called for any errors in our custom code. | ||
@@ -1136,6 +1227,22 @@ // This is not necessary for the updateUserWithValues call, because the Statsig client will | ||
throw _context12.t0; | ||
case 12: | ||
success = Statsig.updateUserWithValues(user, initializeValues.experimentValues); | ||
case 13: | ||
success = true; | ||
errorMessage = null; | ||
_context12.prev = 15; | ||
this.dataAdapter.setBootstrapData(initializeValues.experimentValues); | ||
this.user = user; | ||
_context12.next = 20; | ||
return this.statsigClient.updateUserAsync(this.user); | ||
case 20: | ||
_context12.next = 26; | ||
break; | ||
case 22: | ||
_context12.prev = 22; | ||
_context12.t1 = _context12["catch"](15); | ||
success = false; | ||
errorMessage = String(_context12.t1); | ||
case 26: | ||
(_this$initOptions = this.initOptions) === null || _this$initOptions === void 0 || (_this$initOptions$upd = _this$initOptions.updateUserCompletionCallback) === null || _this$initOptions$upd === void 0 || _this$initOptions$upd.call(_this$initOptions, success, errorMessage); | ||
if (!success) { | ||
_context12.next = 19; | ||
_context12.next = 33; | ||
break; | ||
@@ -1146,11 +1253,11 @@ } | ||
this.subscriptions.anyUpdated(); | ||
_context12.next = 20; | ||
_context12.next = 34; | ||
break; | ||
case 19: | ||
case 33: | ||
throw new Error('Failed to update user. An unexpected error occured.'); | ||
case 20: | ||
case 34: | ||
case "end": | ||
return _context12.stop(); | ||
} | ||
}, _callee12, this, [[0, 7]]); | ||
}, _callee12, this, [[1, 8], [15, 22]]); | ||
})); | ||
@@ -1161,10 +1268,10 @@ function updateStatsigClientUser(_x31, _x32, _x33) { | ||
return updateStatsigClientUser; | ||
}() | ||
}()) | ||
}, { | ||
key: "getPackageVersion", | ||
value: | ||
/** | ||
* @returns string version of the current package in semver style. | ||
*/ | ||
) | ||
}, { | ||
key: "getPackageVersion", | ||
value: function getPackageVersion() { | ||
function getPackageVersion() { | ||
return CLIENT_VERSION; | ||
@@ -1194,6 +1301,8 @@ } | ||
try { | ||
this.assertInitialized(this.statsigClient); | ||
var _options$fireLayerExp = options.fireLayerExposure, | ||
fireLayerExposure = _options$fireLayerExp === void 0 ? true : _options$fireLayerExp; | ||
var evalMethod = fireLayerExposure ? Statsig.getLayer.bind(Statsig) : Statsig.getLayerWithExposureLoggingDisabled.bind(Statsig); | ||
return evalMethod(layerName); | ||
return Layer.fromLayer(this.statsigClient.getLayer(layerName, { | ||
disableExposureLog: !fireLayerExposure | ||
})); | ||
} catch (error) { | ||
@@ -1212,6 +1321,5 @@ // Log the first occurrence of the error | ||
// Return a default value | ||
return Layer._create(layerName, {}, '', { | ||
time: Date.now(), | ||
reason: EvaluationReason.Error | ||
}); | ||
return Layer.fromLayer(_makeLayer(layerName, { | ||
reason: 'Error' | ||
}, null)); | ||
} | ||
@@ -1218,0 +1326,0 @@ } |
@@ -7,3 +7,4 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; | ||
import { CLIENT_VERSION } from './version'; | ||
export { DynamicConfig, EvaluationReason } from 'statsig-js-lite'; | ||
export { EvaluationReason } from './compat/types'; | ||
export { DynamicConfig } from './compat/DynamicConfig'; | ||
export { FeatureGateEnvironment, PerimeterType } from './types'; | ||
@@ -75,17 +76,14 @@ export { CLIENT_VERSION } from './version'; | ||
// Log the first occurrence of the error | ||
if (!_FeatureGates.hasCheckGateErrorOccurred) { | ||
// Log the first occurrence of the error | ||
if (!_FeatureGates.hasGetExperimentValueErrorOccurred) { | ||
// eslint-disable-next-line no-console | ||
console.warn({ | ||
msg: 'An error has occurred getting the experiment value from criterion override. Only the first occurrence of this error is logged.', | ||
experimentName: experimentName, | ||
defaultValue: defaultValue, | ||
options: options, | ||
error: error | ||
}); | ||
_FeatureGates.hasGetExperimentValueErrorOccurred = true; | ||
} | ||
return defaultValue; | ||
if (!_FeatureGates.hasGetExperimentValueErrorOccurred) { | ||
// eslint-disable-next-line no-console | ||
console.warn({ | ||
msg: 'An error has occurred getting the experiment value from criterion override. Only the first occurrence of this error is logged.', | ||
experimentName: experimentName, | ||
defaultValue: defaultValue, | ||
options: options, | ||
error: error | ||
}); | ||
_FeatureGates.hasGetExperimentValueErrorOccurred = true; | ||
} | ||
return defaultValue; | ||
} | ||
@@ -92,0 +90,0 @@ |
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; | ||
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; | ||
import _defineProperty from "@babel/runtime/helpers/defineProperty"; | ||
var _excluded = ["sdkKey", "updateUserCompletionCallback", "perimeter"]; | ||
var _excluded = ["api", "disableCurrentPageLogging", "loggingIntervalMillis", "loggingBufferMaxSize", "localMode", "eventLoggingApi", "eventLoggingApiForRetries", "disableLocalStorage", "ignoreWindowUndefined", "disableAllLogging", "initTimeoutMs", "disableNetworkKeepalive", "overrideStableID", "disableErrorLogging", "disableAutoMetricsLogging"]; | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
import { isFedRamp } from '@atlaskit/atlassian-context'; | ||
import { EvaluationReason } from './compat/types'; | ||
import { PerimeterType } from './types'; | ||
@@ -65,36 +66,50 @@ export var getOptionsWithDefaults = function getOptionsWithDefaults(options) { | ||
}; | ||
/** | ||
* This method transforms the options given by the user into the format accepted by the Statsig | ||
* client. | ||
*/ | ||
export var toStatsigOptions = function toStatsigOptions(options, initializeValues) { | ||
var sdkKey = options.sdkKey, | ||
updateUserCompletionCallback = options.updateUserCompletionCallback, | ||
perimeter = options.perimeter, | ||
restClientOptions = _objectWithoutProperties(options, _excluded); | ||
return _objectSpread(_objectSpread({}, restClientOptions), {}, { | ||
initializeValues: initializeValues, | ||
environment: { | ||
tier: options.environment | ||
export var migrateInitializationOptions = function migrateInitializationOptions(options) { | ||
var api = options.api, | ||
disableCurrentPageLogging = options.disableCurrentPageLogging, | ||
loggingIntervalMillis = options.loggingIntervalMillis, | ||
loggingBufferMaxSize = options.loggingBufferMaxSize, | ||
localMode = options.localMode, | ||
eventLoggingApi = options.eventLoggingApi, | ||
eventLoggingApiForRetries = options.eventLoggingApiForRetries, | ||
disableLocalStorage = options.disableLocalStorage, | ||
ignoreWindowUndefined = options.ignoreWindowUndefined, | ||
disableAllLogging = options.disableAllLogging, | ||
_initTimeoutMs = options.initTimeoutMs, | ||
_disableNetworkKeepalive = options.disableNetworkKeepalive, | ||
_overrideStableID = options.overrideStableID, | ||
_disableErrorLogging = options.disableErrorLogging, | ||
_disableAutoMetricsLogging = options.disableAutoMetricsLogging, | ||
rest = _objectWithoutProperties(options, _excluded); | ||
return _objectSpread(_objectSpread({}, rest), {}, { | ||
networkConfig: { | ||
api: api, | ||
logEventUrl: eventLoggingApi ? eventLoggingApi + 'rgstr' : undefined, | ||
logEventFallbackUrls: eventLoggingApiForRetries ? [eventLoggingApiForRetries] : undefined, | ||
preventAllNetworkTraffic: localMode || !ignoreWindowUndefined && typeof window === 'undefined' | ||
}, | ||
disableCurrentPageLogging: true | ||
}, options.updateUserCompletionCallback && { | ||
updateUserCompletionCallback: toStatsigUpdateUserCompletionCallback(options.updateUserCompletionCallback) | ||
includeCurrentPageUrlWithEvents: !disableCurrentPageLogging, | ||
loggingIntervalMs: loggingIntervalMillis, | ||
loggingBufferMaxSize: loggingBufferMaxSize, | ||
disableStorage: disableLocalStorage, | ||
disableLogging: disableAllLogging | ||
}); | ||
}; | ||
/** | ||
* This method transforms an UpdateUserCompletionCallback in our own format into the format | ||
* accepted by the Statsig client. | ||
*/ | ||
export var toStatsigUpdateUserCompletionCallback = function toStatsigUpdateUserCompletionCallback(callback) { | ||
/** | ||
* The duration passed to the callback indicates how long the update took, but it is deceptive | ||
* since it only times the Statsig code and doesn't account for all of the extra custom work we | ||
* do to obtain the bootstrap values. As a result, we just suppress this parameter in our own | ||
* callback rather than trying to keep it accurate. | ||
*/ | ||
return function (_duration, success, message) { | ||
callback(success, message); | ||
var evaluationReasonMappings = Object.entries(EvaluationReason).map(function (_ref5) { | ||
var _ref6 = _slicedToArray(_ref5, 2), | ||
key = _ref6[0], | ||
value = _ref6[1]; | ||
return [key.toLowerCase(), value]; | ||
}); | ||
export var migrateEvaluationDetails = function migrateEvaluationDetails(details) { | ||
var _evaluationReasonMapp, _evaluationReasonMapp2, _details$receivedAt; | ||
var reasonLower = details.reason.toLowerCase(); | ||
return { | ||
reason: (_evaluationReasonMapp = (_evaluationReasonMapp2 = evaluationReasonMappings.find(function (_ref7) { | ||
var _ref8 = _slicedToArray(_ref7, 1), | ||
key = _ref8[0]; | ||
return reasonLower.includes(key); | ||
})) === null || _evaluationReasonMapp2 === void 0 ? void 0 : _evaluationReasonMapp2[1]) !== null && _evaluationReasonMapp !== void 0 ? _evaluationReasonMapp : EvaluationReason.Unknown, | ||
time: (_details$receivedAt = details.receivedAt) !== null && _details$receivedAt !== void 0 ? _details$receivedAt : Date.now() | ||
}; | ||
}; |
/// <reference types="node" /> | ||
export var CLIENT_VERSION = "4.23.4"; | ||
export var CLIENT_VERSION = "4.24.0"; |
@@ -1,3 +0,4 @@ | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION, | ||
// Statsig | ||
DynamicConfig, EvaluationReason } from './client/FeatureGates'; | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION } from './client/FeatureGates'; | ||
export { DynamicConfig } from './client/compat/DynamicConfig'; | ||
export { Layer } from './client/compat/Layer'; | ||
export { EvaluationReason } from './client/compat/types'; |
@@ -1,5 +0,10 @@ | ||
import { DynamicConfig, Layer, type LocalOverrides } from 'statsig-js-lite'; | ||
import { StatsigClient } from '@statsig/js-client'; | ||
import { DynamicConfig } from './compat/DynamicConfig'; | ||
import { Layer } from './compat/Layer'; | ||
import { type FetcherOptions } from './fetcher'; | ||
import { type LocalOverrides } from './PersistentOverrideAdapter'; | ||
import { type BaseClientOptions, type CheckGateOptions, type ClientOptions, type CustomAttributes, type FromValuesClientOptions, type GetExperimentOptions, type GetExperimentValueOptions, type GetLayerOptions, type GetLayerValueOptions, type Identifiers, type Provider } from './types'; | ||
export declare class Client { | ||
private statsigClient?; | ||
private user?; | ||
private initOptions?; | ||
@@ -24,2 +29,4 @@ private initPromise; | ||
private subscriptions; | ||
private dataAdapter; | ||
private overrideAdapter; | ||
/** | ||
@@ -63,2 +70,3 @@ * @description | ||
initializeFromValues(clientOptions: FromValuesClientOptions, identifiers: Identifiers, customAttributes?: CustomAttributes, initializeValues?: Record<string, unknown>): Promise<void>; | ||
protected assertInitialized(statsigClient: StatsigClient | undefined): asserts statsigClient; | ||
/** | ||
@@ -183,3 +191,3 @@ * This method updates the user using a network call to fetch the new set of values. | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -204,3 +212,3 @@ * is called. If you are using this API for testing purposes, you should call | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -227,3 +235,3 @@ * is called. If you are using this API for testing purposes, you should call | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -326,2 +334,7 @@ * is called. If you are using this API for testing purposes, you should call | ||
/** | ||
* Call this if modifying the values being served by the Statsig library since it has its own | ||
* memoization cache which will not be updated if the values are changed outside of the library. | ||
*/ | ||
protected statsigValuesUpdated: () => void; | ||
/** | ||
* @returns string version of the current package in semver style. | ||
@@ -328,0 +341,0 @@ */ |
import { Client } from './Client'; | ||
import { type FeatureFlagValue, type WithDocComments } from './types'; | ||
export type { EvaluationDetails, LocalOverrides } from 'statsig-js-lite'; | ||
export { DynamicConfig, EvaluationReason } from 'statsig-js-lite'; | ||
export { type EvaluationDetails, EvaluationReason } from './compat/types'; | ||
export type { LocalOverrides } from './PersistentOverrideAdapter'; | ||
export { DynamicConfig } from './compat/DynamicConfig'; | ||
export type { AnalyticsWebClient, BaseClientOptions, CheckGateOptions, ClientOptions, CustomAttributes, FromValuesClientOptions, FrontendExperimentsResult, GetExperimentOptions, GetExperimentValueOptions, Identifiers, InitializeValues, OptionsWithDefaults, UpdateUserCompletionCallback, Provider, } from './types'; | ||
@@ -40,3 +41,3 @@ export { FeatureGateEnvironment, PerimeterType } from './types'; | ||
static manuallyLogGateExposure: (gateName: string) => void; | ||
static getExperiment: (experimentName: string, options?: import("./types").GetExperimentOptions) => import("statsig-js-lite").DynamicConfig; | ||
static getExperiment: (experimentName: string, options?: import("./types").GetExperimentOptions) => import("./compat/DynamicConfig").DynamicConfig; | ||
static manuallyLogExperimentExposure: (experimentName: string) => void; | ||
@@ -49,4 +50,4 @@ static manuallyLogLayerExposure: (layerName: string, parameterName: string) => void; | ||
static clearConfigOverride: (experimentName: string) => void; | ||
static setOverrides: (overrides: Partial<import("statsig-js-lite").LocalOverrides>) => void; | ||
static getOverrides: () => import("statsig-js-lite").LocalOverrides; | ||
static setOverrides: (overrides: Partial<import("./PersistentOverrideAdapter").LocalOverrides>) => void; | ||
static getOverrides: () => import("./PersistentOverrideAdapter").LocalOverrides; | ||
static clearAllOverrides: () => void; | ||
@@ -61,3 +62,3 @@ static isCurrentUser: (identifiers: import("./types").Identifiers, customAttributes?: import("./types").CustomAttributes | undefined) => boolean; | ||
static getPackageVersion: () => string; | ||
static getLayer: (layerName: string, options?: import("./types").GetLayerOptions) => import("statsig-js-lite").Layer; | ||
static getLayer: (layerName: string, options?: import("./types").GetLayerOptions) => import("..").Layer; | ||
static getLayerValue: <T>(layerName: string, parameterName: string, defaultValue: T, options?: import("./types").GetLayerValueOptions<T>) => T; | ||
@@ -64,0 +65,0 @@ } |
@@ -1,2 +0,3 @@ | ||
import { type StatsigOptions } from 'statsig-js-lite'; | ||
import type { StatsigOptions as NewStatsigOptions } from '@statsig/js-client'; | ||
import type { StatsigOptions } from './compat/types'; | ||
/** | ||
@@ -26,3 +27,4 @@ * The identifiers for the user. Options are restricted to the set that is currently supported. | ||
export type UpdateUserCompletionCallback = (success: boolean, message: string | null) => void; | ||
type FeatureGateOptions = StatsigOptions; | ||
export type FeatureGateOptions = Omit<StatsigOptions, 'environment' | 'initializeValues' | 'sdkKey' | 'updateUserCompletionCallback'>; | ||
export type NewFeatureGateOptions = Omit<NewStatsigOptions, 'environment' | 'initializeValues' | 'sdkKey' | 'updateUserCompletionCallback'>; | ||
type OperationalEventPayload = { | ||
@@ -47,3 +49,3 @@ action: string; | ||
*/ | ||
export interface BaseClientOptions extends Omit<FeatureGateOptions, 'environment' | 'initializeValues' | 'sdkKey' | 'updateUserCompletionCallback'> { | ||
export interface BaseClientOptions extends FeatureGateOptions { | ||
environment: FeatureGateEnvironment; | ||
@@ -50,0 +52,0 @@ targetApp: string; |
@@ -1,3 +0,4 @@ | ||
import type { StatsigOptions, StatsigUser } from 'statsig-js-lite'; | ||
import { type BaseClientOptions, type CustomAttributes, type FromValuesClientOptions, type Identifiers, type OptionsWithDefaults, type UpdateUserCompletionCallback } from './types'; | ||
import type { EvaluationDetails as NewEvaluationDetails, StatsigUser } from '@statsig/js-client'; | ||
import { type EvaluationDetails } from './compat/types'; | ||
import { type BaseClientOptions, type CustomAttributes, type FeatureGateOptions, type Identifiers, type NewFeatureGateOptions, type OptionsWithDefaults } from './types'; | ||
export declare const getOptionsWithDefaults: <T extends BaseClientOptions>(options: T) => OptionsWithDefaults<T>; | ||
@@ -10,13 +11,3 @@ export declare const shallowEquals: (objectA?: object, objectB?: object) => boolean; | ||
export declare const toStatsigUser: (identifiers: Identifiers, customAttributes?: CustomAttributes) => StatsigUser; | ||
/** | ||
* This method transforms the options given by the user into the format accepted by the Statsig | ||
* client. | ||
*/ | ||
export declare const toStatsigOptions: (options: FromValuesClientOptions, initializeValues: Record<string, unknown>) => StatsigOptions; | ||
type StatsigUpdateUserCompletionCallback = NonNullable<StatsigOptions['updateUserCompletionCallback']>; | ||
/** | ||
* This method transforms an UpdateUserCompletionCallback in our own format into the format | ||
* accepted by the Statsig client. | ||
*/ | ||
export declare const toStatsigUpdateUserCompletionCallback: (callback: UpdateUserCompletionCallback) => StatsigUpdateUserCompletionCallback; | ||
export {}; | ||
export declare const migrateInitializationOptions: <T extends FeatureGateOptions>(options: T) => Omit<T, keyof FeatureGateOptions> & NewFeatureGateOptions; | ||
export declare const migrateEvaluationDetails: (details: NewEvaluationDetails) => EvaluationDetails; |
@@ -1,2 +0,6 @@ | ||
export type { AnalyticsWebClient, BaseClientOptions, CheckGateOptions, ClientOptions, CustomAttributes, FrontendExperimentsResult, FromValuesClientOptions, GetExperimentOptions, GetExperimentValueOptions, Identifiers, InitializeValues, UpdateUserCompletionCallback, OptionsWithDefaults, Provider, EvaluationDetails, LocalOverrides, } from './client/FeatureGates'; | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION, DynamicConfig, EvaluationReason, } from './client/FeatureGates'; | ||
export type { AnalyticsWebClient, BaseClientOptions, CheckGateOptions, ClientOptions, CustomAttributes, FrontendExperimentsResult, FromValuesClientOptions, GetExperimentOptions, GetExperimentValueOptions, Identifiers, InitializeValues, UpdateUserCompletionCallback, OptionsWithDefaults, Provider, } from './client/FeatureGates'; | ||
export type { LocalOverrides } from './client/PersistentOverrideAdapter'; | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION, } from './client/FeatureGates'; | ||
export { DynamicConfig } from './client/compat/DynamicConfig'; | ||
export { Layer } from './client/compat/Layer'; | ||
export { EvaluationReason, type EvaluationDetails } from './client/compat/types'; |
@@ -1,5 +0,10 @@ | ||
import { DynamicConfig, Layer, type LocalOverrides } from 'statsig-js-lite'; | ||
import { StatsigClient } from '@statsig/js-client'; | ||
import { DynamicConfig } from './compat/DynamicConfig'; | ||
import { Layer } from './compat/Layer'; | ||
import { type FetcherOptions } from './fetcher'; | ||
import { type LocalOverrides } from './PersistentOverrideAdapter'; | ||
import { type BaseClientOptions, type CheckGateOptions, type ClientOptions, type CustomAttributes, type FromValuesClientOptions, type GetExperimentOptions, type GetExperimentValueOptions, type GetLayerOptions, type GetLayerValueOptions, type Identifiers, type Provider } from './types'; | ||
export declare class Client { | ||
private statsigClient?; | ||
private user?; | ||
private initOptions?; | ||
@@ -24,2 +29,4 @@ private initPromise; | ||
private subscriptions; | ||
private dataAdapter; | ||
private overrideAdapter; | ||
/** | ||
@@ -63,2 +70,3 @@ * @description | ||
initializeFromValues(clientOptions: FromValuesClientOptions, identifiers: Identifiers, customAttributes?: CustomAttributes, initializeValues?: Record<string, unknown>): Promise<void>; | ||
protected assertInitialized(statsigClient: StatsigClient | undefined): asserts statsigClient; | ||
/** | ||
@@ -183,3 +191,3 @@ * This method updates the user using a network call to fetch the new set of values. | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -204,3 +212,3 @@ * is called. If you are using this API for testing purposes, you should call | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -227,3 +235,3 @@ * is called. If you are using this API for testing purposes, you should call | ||
* | ||
* Overrides are persisted to the `STATSIG_JS_LITE_LOCAL_OVERRIDES` key in localStorage, so they | ||
* Overrides are persisted to the `STATSIG_OVERRIDES` key in localStorage, so they | ||
* will continue to affect every client that is initialized on the same domain after this method | ||
@@ -326,2 +334,7 @@ * is called. If you are using this API for testing purposes, you should call | ||
/** | ||
* Call this if modifying the values being served by the Statsig library since it has its own | ||
* memoization cache which will not be updated if the values are changed outside of the library. | ||
*/ | ||
protected statsigValuesUpdated: () => void; | ||
/** | ||
* @returns string version of the current package in semver style. | ||
@@ -328,0 +341,0 @@ */ |
import { Client } from './Client'; | ||
import { type FeatureFlagValue, type WithDocComments } from './types'; | ||
export type { EvaluationDetails, LocalOverrides } from 'statsig-js-lite'; | ||
export { DynamicConfig, EvaluationReason } from 'statsig-js-lite'; | ||
export { type EvaluationDetails, EvaluationReason } from './compat/types'; | ||
export type { LocalOverrides } from './PersistentOverrideAdapter'; | ||
export { DynamicConfig } from './compat/DynamicConfig'; | ||
export type { AnalyticsWebClient, BaseClientOptions, CheckGateOptions, ClientOptions, CustomAttributes, FromValuesClientOptions, FrontendExperimentsResult, GetExperimentOptions, GetExperimentValueOptions, Identifiers, InitializeValues, OptionsWithDefaults, UpdateUserCompletionCallback, Provider, } from './types'; | ||
@@ -40,3 +41,3 @@ export { FeatureGateEnvironment, PerimeterType } from './types'; | ||
static manuallyLogGateExposure: (gateName: string) => void; | ||
static getExperiment: (experimentName: string, options?: import("./types").GetExperimentOptions) => import("statsig-js-lite").DynamicConfig; | ||
static getExperiment: (experimentName: string, options?: import("./types").GetExperimentOptions) => import("./compat/DynamicConfig").DynamicConfig; | ||
static manuallyLogExperimentExposure: (experimentName: string) => void; | ||
@@ -49,4 +50,4 @@ static manuallyLogLayerExposure: (layerName: string, parameterName: string) => void; | ||
static clearConfigOverride: (experimentName: string) => void; | ||
static setOverrides: (overrides: Partial<import("statsig-js-lite").LocalOverrides>) => void; | ||
static getOverrides: () => import("statsig-js-lite").LocalOverrides; | ||
static setOverrides: (overrides: Partial<import("./PersistentOverrideAdapter").LocalOverrides>) => void; | ||
static getOverrides: () => import("./PersistentOverrideAdapter").LocalOverrides; | ||
static clearAllOverrides: () => void; | ||
@@ -61,3 +62,3 @@ static isCurrentUser: (identifiers: import("./types").Identifiers, customAttributes?: import("./types").CustomAttributes | undefined) => boolean; | ||
static getPackageVersion: () => string; | ||
static getLayer: (layerName: string, options?: import("./types").GetLayerOptions) => import("statsig-js-lite").Layer; | ||
static getLayer: (layerName: string, options?: import("./types").GetLayerOptions) => import("..").Layer; | ||
static getLayerValue: <T>(layerName: string, parameterName: string, defaultValue: T, options?: import("./types").GetLayerValueOptions<T>) => T; | ||
@@ -64,0 +65,0 @@ } |
@@ -1,2 +0,3 @@ | ||
import { type StatsigOptions } from 'statsig-js-lite'; | ||
import type { StatsigOptions as NewStatsigOptions } from '@statsig/js-client'; | ||
import type { StatsigOptions } from './compat/types'; | ||
/** | ||
@@ -26,3 +27,4 @@ * The identifiers for the user. Options are restricted to the set that is currently supported. | ||
export type UpdateUserCompletionCallback = (success: boolean, message: string | null) => void; | ||
type FeatureGateOptions = StatsigOptions; | ||
export type FeatureGateOptions = Omit<StatsigOptions, 'environment' | 'initializeValues' | 'sdkKey' | 'updateUserCompletionCallback'>; | ||
export type NewFeatureGateOptions = Omit<NewStatsigOptions, 'environment' | 'initializeValues' | 'sdkKey' | 'updateUserCompletionCallback'>; | ||
type OperationalEventPayload = { | ||
@@ -47,3 +49,3 @@ action: string; | ||
*/ | ||
export interface BaseClientOptions extends Omit<FeatureGateOptions, 'environment' | 'initializeValues' | 'sdkKey' | 'updateUserCompletionCallback'> { | ||
export interface BaseClientOptions extends FeatureGateOptions { | ||
environment: FeatureGateEnvironment; | ||
@@ -50,0 +52,0 @@ targetApp: string; |
@@ -1,3 +0,4 @@ | ||
import type { StatsigOptions, StatsigUser } from 'statsig-js-lite'; | ||
import { type BaseClientOptions, type CustomAttributes, type FromValuesClientOptions, type Identifiers, type OptionsWithDefaults, type UpdateUserCompletionCallback } from './types'; | ||
import type { EvaluationDetails as NewEvaluationDetails, StatsigUser } from '@statsig/js-client'; | ||
import { type EvaluationDetails } from './compat/types'; | ||
import { type BaseClientOptions, type CustomAttributes, type FeatureGateOptions, type Identifiers, type NewFeatureGateOptions, type OptionsWithDefaults } from './types'; | ||
export declare const getOptionsWithDefaults: <T extends BaseClientOptions>(options: T) => OptionsWithDefaults<T>; | ||
@@ -10,13 +11,3 @@ export declare const shallowEquals: (objectA?: object, objectB?: object) => boolean; | ||
export declare const toStatsigUser: (identifiers: Identifiers, customAttributes?: CustomAttributes) => StatsigUser; | ||
/** | ||
* This method transforms the options given by the user into the format accepted by the Statsig | ||
* client. | ||
*/ | ||
export declare const toStatsigOptions: (options: FromValuesClientOptions, initializeValues: Record<string, unknown>) => StatsigOptions; | ||
type StatsigUpdateUserCompletionCallback = NonNullable<StatsigOptions['updateUserCompletionCallback']>; | ||
/** | ||
* This method transforms an UpdateUserCompletionCallback in our own format into the format | ||
* accepted by the Statsig client. | ||
*/ | ||
export declare const toStatsigUpdateUserCompletionCallback: (callback: UpdateUserCompletionCallback) => StatsigUpdateUserCompletionCallback; | ||
export {}; | ||
export declare const migrateInitializationOptions: <T extends FeatureGateOptions>(options: T) => Omit<T, keyof FeatureGateOptions> & NewFeatureGateOptions; | ||
export declare const migrateEvaluationDetails: (details: NewEvaluationDetails) => EvaluationDetails; |
@@ -1,2 +0,6 @@ | ||
export type { AnalyticsWebClient, BaseClientOptions, CheckGateOptions, ClientOptions, CustomAttributes, FrontendExperimentsResult, FromValuesClientOptions, GetExperimentOptions, GetExperimentValueOptions, Identifiers, InitializeValues, UpdateUserCompletionCallback, OptionsWithDefaults, Provider, EvaluationDetails, LocalOverrides, } from './client/FeatureGates'; | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION, DynamicConfig, EvaluationReason, } from './client/FeatureGates'; | ||
export type { AnalyticsWebClient, BaseClientOptions, CheckGateOptions, ClientOptions, CustomAttributes, FrontendExperimentsResult, FromValuesClientOptions, GetExperimentOptions, GetExperimentValueOptions, Identifiers, InitializeValues, UpdateUserCompletionCallback, OptionsWithDefaults, Provider, } from './client/FeatureGates'; | ||
export type { LocalOverrides } from './client/PersistentOverrideAdapter'; | ||
export { default, FeatureGateEnvironment, PerimeterType, CLIENT_VERSION, } from './client/FeatureGates'; | ||
export { DynamicConfig } from './client/compat/DynamicConfig'; | ||
export { Layer } from './client/compat/Layer'; | ||
export { EvaluationReason, type EvaluationDetails } from './client/compat/types'; |
{ | ||
"name": "@atlaskit/feature-gate-js-client", | ||
"version": "4.23.4", | ||
"version": "4.24.0", | ||
"description": "Atlassians wrapper for the Statsig js-lite client.", | ||
@@ -31,3 +31,4 @@ "author": "Atlassian Pty Ltd", | ||
"af:exports": { | ||
".": "./src/index.ts" | ||
".": "./src/index.ts", | ||
"./client": "./src/client.ts" | ||
}, | ||
@@ -37,4 +38,5 @@ "dependencies": { | ||
"@babel/runtime": "^7.0.0", | ||
"eventemitter2": "^4.1.0", | ||
"statsig-js-lite": "^1.6.0" | ||
"@statsig/client-core": "^3.10.0", | ||
"@statsig/js-client": "^3.10.0", | ||
"eventemitter2": "^4.1.0" | ||
}, | ||
@@ -41,0 +43,0 @@ "devDependencies": { |
@@ -441,2 +441,26 @@ # FeatureGateJsClient | ||
### Multiple clients on a single page | ||
Typically we don't allow multiple usages of the feature gate client on a single page because the | ||
client makes a lot of heavy network calls which could have a drastic performance impact for | ||
customers if many clients were to exist on a single page. However there are some cases where a | ||
seperate client to the product is absolutely necessary. We expose a way to instantiate a new client | ||
instead of using the static methods for this case. | ||
Due to the performance implications **please ask us in #help-statsig-switcheroo before using the | ||
standalone client** so that we can check if there are any alternative solutions that won't impact | ||
customers and make us aware of the cases where separate clients are necessary. | ||
```typescript | ||
import FeatureGateClient from '@atlaskit/feature-gate-js-client/client'; | ||
const featureGates = new FeatureGateClient(); | ||
// Usage is the same as the static API | ||
await featureGates.initialize({ | ||
// ... | ||
}); | ||
featureGates.checkGate('my-gate'); | ||
``` | ||
## Testing | ||
@@ -443,0 +467,0 @@ |
447253
95
8426
798
5
+ Added@statsig/client-core@^3.10.0
+ Added@statsig/js-client@^3.10.0
+ Added@statsig/client-core@3.12.1(transitive)
+ Added@statsig/js-client@3.12.1(transitive)
- Removedstatsig-js-lite@^1.6.0
- Removedstatsig-js-lite@1.6.0(transitive)