"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UserScopedGrowthBook = exports.GrowthBookClient = void 0; var _util = require("./util"); var _featureRepository = require("./feature-repository"); var _core = require("./core"); const SDK_VERSION = (0, _util.loadSDKVersion)(); class GrowthBookClient { // Properties and methods that start with "_" are mangled by Terser (saves ~150 bytes) constructor(options) { options = options || {}; // These properties are all initialized in the constructor instead of above // This saves ~80 bytes in the final output this.version = SDK_VERSION; this._options = options; this.debug = !!options.debug; this.ready = false; this._features = {}; this._experiments = []; this.log = this.log.bind(this); if (options.plugins) { for (const plugin of options.plugins) { plugin(this); } } } async setPayload(payload) { this._payload = payload; const data = await (0, _core.decryptPayload)(payload, this._options.decryptionKey); this._decryptedPayload = data; if (data.features) { this._features = data.features; } if (data.experiments) { this._experiments = data.experiments; } if (data.savedGroups) { this._options.savedGroups = data.savedGroups; } this.ready = true; } initSync(options) { const payload = options.payload; if (payload.encryptedExperiments || payload.encryptedFeatures) { throw new Error("initSync does not support encrypted payloads"); } this._payload = payload; this._decryptedPayload = payload; if (payload.features) { this._features = payload.features; } if (payload.experiments) { this._experiments = payload.experiments; } this.ready = true; (0, _featureRepository.startStreaming)(this, options); return this; } async init(options) { options = options || {}; if (options.cacheSettings) { (0, _featureRepository.configureCache)(options.cacheSettings); } if (options.payload) { await this.setPayload(options.payload); (0, _featureRepository.startStreaming)(this, options); return { success: true, source: "init" }; } else { const { data, ...res } = await this._refresh({ ...options, allowStale: true }); (0, _featureRepository.startStreaming)(this, options); await this.setPayload(data || {}); return res; } } async refreshFeatures(options) { const res = await this._refresh({ ...(options || {}), allowStale: false }); if (res.data) { await this.setPayload(res.data); } } getApiInfo() { return [this.getApiHosts().apiHost, this.getClientKey()]; } getApiHosts() { return (0, _core.getApiHosts)(this._options); } getClientKey() { return this._options.clientKey || ""; } getPayload() { return this._payload || { features: this.getFeatures(), experiments: this._experiments || [] }; } getDecryptedPayload() { return this._decryptedPayload || this.getPayload(); } async _refresh({ timeout, skipCache, allowStale, streaming }) { if (!this._options.clientKey) { throw new Error("Missing clientKey"); } // Trigger refresh in feature repository return (0, _featureRepository.refreshFeatures)({ instance: this, timeout, skipCache: skipCache || this._options.disableCache, allowStale, backgroundSync: streaming ?? true }); } getFeatures() { return this._features || {}; } getGlobalAttributes() { return this._options.globalAttributes || {}; } setGlobalAttributes(attributes) { this._options.globalAttributes = attributes; } destroy(options) { options = options || {}; this._destroyed = true; (0, _featureRepository.unsubscribe)(this); if (options.destroyAllStreams) { (0, _featureRepository.clearAutoRefresh)(); } // Release references to save memory this._features = {}; this._experiments = []; this._decryptedPayload = undefined; this._payload = undefined; this._options = {}; } isDestroyed() { return !!this._destroyed; } setEventLogger(logger) { this._options.eventLogger = logger; } logEvent(eventName, properties, userContext) { if (this._options.eventLogger) { const ctx = this._getEvalContext(userContext); this._options.eventLogger(eventName, properties, ctx.user); } } runInlineExperiment(experiment, userContext) { const { result } = (0, _core.runExperiment)(experiment, null, this._getEvalContext(userContext)); return result; } _getEvalContext(userContext) { if (this._options.globalAttributes) { userContext = { ...userContext, attributes: { ...this._options.globalAttributes, ...userContext.attributes } }; } return { user: userContext, global: this._getGlobalContext(), stack: { evaluatedFeatures: new Set() } }; } _getGlobalContext() { return { features: this._features, experiments: this._experiments, log: this.log, enabled: this._options.enabled, qaMode: this._options.qaMode, savedGroups: this._options.savedGroups, forcedFeatureValues: this._options.forcedFeatureValues, forcedVariations: this._options.forcedVariations, trackingCallback: this._options.trackingCallback, onFeatureUsage: this._options.onFeatureUsage }; } isOn(key, userContext) { return this.evalFeature(key, userContext).on; } isOff(key, userContext) { return this.evalFeature(key, userContext).off; } getFeatureValue(key, defaultValue, userContext) { const value = this.evalFeature(key, userContext).value; return value === null ? defaultValue : value; } evalFeature(id, userContext) { return (0, _core.evalFeature)(id, this._getEvalContext(userContext)); } log(msg, ctx) { if (!this.debug) return; if (this._options.log) this._options.log(msg, ctx);else console.log(msg, ctx); } setTrackingCallback(callback) { this._options.trackingCallback = callback; } setFeatureUsageCallback(callback) { this._options.onFeatureUsage = callback; } async applyStickyBuckets(partialContext, stickyBucketService) { const ctx = this._getEvalContext(partialContext); const stickyBucketAssignmentDocs = await (0, _core.getAllStickyBucketAssignmentDocs)(ctx, stickyBucketService); return { ...partialContext, stickyBucketAssignmentDocs, saveStickyBucketAssignmentDoc: doc => stickyBucketService.saveAssignments(doc) }; } createScopedInstance(userContext, userPlugins) { return new UserScopedGrowthBook(this, userContext, [...(this._options.plugins || []), ...(userPlugins || [])]); } } exports.GrowthBookClient = GrowthBookClient; class UserScopedGrowthBook { constructor(gb, userContext, plugins) { this._gb = gb; this._userContext = userContext; this.logs = []; this._userContext.trackedExperiments = this._userContext.trackedExperiments || new Set(); this._userContext.trackedFeatureUsage = this._userContext.trackedFeatureUsage || {}; this._userContext.devLogs = this.logs; if (plugins) { for (const plugin of plugins) { plugin(this); } } } runInlineExperiment(experiment) { return this._gb.runInlineExperiment(experiment, this._userContext); } isOn(key) { return this._gb.isOn(key, this._userContext); } isOff(key) { return this._gb.isOff(key, this._userContext); } getFeatureValue(key, defaultValue) { return this._gb.getFeatureValue(key, defaultValue, this._userContext); } evalFeature(id) { return this._gb.evalFeature(id, this._userContext); } logEvent(eventName, properties) { if (this._userContext.enableDevMode) { this.logs.push({ eventName, properties, timestamp: Date.now().toString(), logType: "event" }); } this._gb.logEvent(eventName, properties || {}, this._userContext); } setTrackingCallback(cb) { this._userContext.trackingCallback = cb; } getApiInfo() { return this._gb.getApiInfo(); } getClientKey() { return this._gb.getClientKey(); } setURL(url) { this._userContext.url = url; } updateAttributes(attributes) { this._userContext.attributes = { ...this._userContext.attributes, ...attributes }; } setAttributeOverrides(overrides) { this._userContext.attributeOverrides = overrides; } async setForcedVariations(vars) { this._userContext.forcedVariations = vars || {}; } // eslint-disable-next-line setForcedFeatures(map) { this._userContext.forcedFeatureValues = map; } getUserContext() { return this._userContext; } getVersion() { return SDK_VERSION; } getDecryptedPayload() { return this._gb.getDecryptedPayload(); } inDevMode() { return !!this._userContext.enableDevMode; } } exports.UserScopedGrowthBook = UserScopedGrowthBook; //# sourceMappingURL=GrowthBookClient.js.map