UNPKG

posthog-js

Version:

Posthog-js allows you to automatically capture usage and send events to PostHog.

1,692 lines • 88.2 kB
"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostHogFeatureFlags = exports.QuotaLimitedResource = exports.parseFlagsResponse = exports.filterActiveFeatureFlags = exports.FeatureFlagError = void 0;
var general_utils_1 = require("@posthog/browser-common/utils/general-utils");
var feature_flags_config_1 = require("./feature-flags-config");
var extension_tokens_1 = require("./extension-tokens");
var constants_1 = require("./constants");
var core_1 = require("@posthog/core");
var logger_1 = require("@posthog/browser-common/utils/logger");
var event_utils_1 = require("@posthog/browser-common/utils/event-utils");
var globals_1 = require("@posthog/browser-common/utils/globals");
var promise_utils_1 = require("@posthog/browser-common/utils/promise-utils");
var request_utils_1 = require("@posthog/browser-common/utils/request-utils");
var logger = (0, logger_1.createLogger)('[FeatureFlags]');
var forceDebugLogger = (0, logger_1.createLogger)('[FeatureFlags]', { debugEnabled: true });
var FLAG_TIMEOUT_MSG = '" failed. Feature flags didn\'t load in time.';
// Mirrors the event retry queue's status-0 budget: repeated requests that die
// before any HTTP response while the browser reports itself online are usually
// deterministically blocked (ad blocker, CORS, extension). Stop periodic /flags
// refreshes after this many consecutive failures until connectivity changes.
var MAX_CONSECUTIVE_FLAGS_STATUS_ZERO_FAILURES = 3;
/**
 * Error type constants for the $feature_flag_error property.
 *
 * These values are sent in analytics events to track flag evaluation failures.
 * They should not be changed without considering impact on existing dashboards
 * and queries that filter on these values.
 */
exports.FeatureFlagError = {
    ERRORS_WHILE_COMPUTING: 'errors_while_computing_flags',
    FLAG_MISSING: 'flag_missing',
    QUOTA_LIMITED: 'quota_limited',
    TIMEOUT: 'timeout',
    CONNECTION_ERROR: 'connection_error',
    UNKNOWN_ERROR: 'unknown_error',
    apiError: function (status) { return "api_error_".concat(status); },
};
/** Converts an array of flag names to a Record where each flag is set to true. */
var arrayToFlagsRecord = function (flags) {
    var flagsObj = {};
    for (var i = 0; i < flags.length; i++) {
        flagsObj[flags[i]] = true;
    }
    return flagsObj;
};
var filterActiveFeatureFlags = function (featureFlags) {
    var e_1, _a;
    var activeFeatureFlags = {};
    try {
        for (var _b = __values((0, general_utils_1.entries)(featureFlags || {})), _c = _b.next(); !_c.done; _c = _b.next()) {
            var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
            if (value) {
                activeFeatureFlags[key] = value;
            }
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
        }
        finally { if (e_1) throw e_1.error; }
    }
    return activeFeatureFlags;
};
exports.filterActiveFeatureFlags = filterActiveFeatureFlags;
var parseFlagsResponse = function (response, currentFlags, currentFlagPayloads, currentFlagDetails, options, responseLogger) {
    var _a, _b, _c, _d;
    if (currentFlags === void 0) { currentFlags = {}; }
    if (currentFlagPayloads === void 0) { currentFlagPayloads = {}; }
    if (currentFlagDetails === void 0) { currentFlagDetails = {}; }
    if (responseLogger === void 0) { responseLogger = logger; }
    var normalizedResponse = normalizeFlagsResponse(response, responseLogger);
    var flagDetails = normalizedResponse.flags;
    var featureFlags = normalizedResponse.featureFlags;
    var flagPayloads = normalizedResponse.featureFlagPayloads;
    if (!featureFlags) {
        return; // <-- This early return means we don't update anything, which is good.
    }
    var requestId = response['requestId'];
    var evaluatedAt = response['evaluatedAt'];
    // using the v1 api
    if ((0, core_1.isArray)(featureFlags)) {
        responseLogger.warn('v1 of the feature flags endpoint is deprecated. Please use the latest version.');
        var $enabled_feature_flags = {};
        if (featureFlags) {
            for (var i = 0; i < featureFlags.length; i++) {
                $enabled_feature_flags[featureFlags[i]] = true;
            }
        }
        return _a = {},
            _a[constants_1.PERSISTENCE_ACTIVE_FEATURE_FLAGS] = featureFlags,
            _a[constants_1.ENABLED_FEATURE_FLAGS] = $enabled_feature_flags,
            // Legacy responses never carry the gate — fail safe to full events.
            _a[constants_1.PERSISTENCE_MINIMAL_FLAG_CALLED_EVENTS] = false,
            _a;
    }
    // using the v2+ api
    var newFeatureFlags = featureFlags;
    var newFeatureFlagPayloads = flagPayloads;
    var newFeatureFlagDetails = flagDetails;
    if (options === null || options === void 0 ? void 0 : options.partialResponse) {
        // The response is intentionally partial (e.g., only survey flags were requested via
        // advanced_only_evaluate_survey_feature_flags). Merge with existing flags so that
        // bootstrapped or previously loaded non-survey flags are preserved.
        var evaluatedFlagKeys = Object.keys(newFeatureFlags);
        var evaluatedPayloads_1 = newFeatureFlagPayloads || {};
        newFeatureFlags = __assign(__assign({}, currentFlags), newFeatureFlags);
        newFeatureFlagPayloads = __assign(__assign({}, currentFlagPayloads), evaluatedPayloads_1);
        evaluatedFlagKeys.forEach(function (key) {
            if (!(key in evaluatedPayloads_1)) {
                newFeatureFlagPayloads === null || newFeatureFlagPayloads === void 0 ? true : delete newFeatureFlagPayloads[key];
            }
        });
        newFeatureFlagDetails = __assign(__assign({}, currentFlagDetails), newFeatureFlagDetails);
    }
    else if (response.errorsWhileComputingFlags) {
        // if not all flags were computed, we upsert flags instead of replacing them
        // but filter out flags that failed to evaluate so they don't overwrite cached values
        if (flagDetails) {
            var successfulKeys_1 = new Set(Object.keys(flagDetails).filter(function (key) { var _a; return !((_a = flagDetails[key]) === null || _a === void 0 ? void 0 : _a.failed); }));
            newFeatureFlags = __assign(__assign({}, currentFlags), Object.fromEntries(Object.entries(newFeatureFlags).filter(function (_a) {
                var _b = __read(_a, 1), key = _b[0];
                return successfulKeys_1.has(key);
            })));
            var successfulPayloads_1 = Object.fromEntries(Object.entries(newFeatureFlagPayloads || {}).filter(function (_a) {
                var _b = __read(_a, 1), key = _b[0];
                return successfulKeys_1.has(key);
            }));
            newFeatureFlagPayloads = __assign(__assign({}, currentFlagPayloads), successfulPayloads_1);
            successfulKeys_1.forEach(function (key) {
                if (!(key in successfulPayloads_1)) {
                    newFeatureFlagPayloads === null || newFeatureFlagPayloads === void 0 ? true : delete newFeatureFlagPayloads[key];
                }
            });
            newFeatureFlagDetails = __assign(__assign({}, currentFlagDetails), Object.fromEntries(Object.entries(newFeatureFlagDetails || {}).filter(function (_a) {
                var _b = __read(_a, 1), key = _b[0];
                return successfulKeys_1.has(key);
            })));
        }
        else {
            // v1 responses don't have flagDetails, so we can't filter by failed field
            // Fall back to the original merge behavior
            newFeatureFlags = __assign(__assign({}, currentFlags), newFeatureFlags);
            newFeatureFlagPayloads = __assign(__assign({}, currentFlagPayloads), newFeatureFlagPayloads);
            newFeatureFlagDetails = __assign(__assign({}, currentFlagDetails), newFeatureFlagDetails);
        }
    }
    return __assign(__assign((_b = {}, _b[constants_1.PERSISTENCE_ACTIVE_FEATURE_FLAGS] = Object.keys((0, exports.filterActiveFeatureFlags)(newFeatureFlags)), _b[constants_1.ENABLED_FEATURE_FLAGS] = newFeatureFlags || {}, _b[constants_1.PERSISTENCE_FEATURE_FLAG_PAYLOADS] = newFeatureFlagPayloads || {}, _b[constants_1.PERSISTENCE_FEATURE_FLAG_DETAILS] = newFeatureFlagDetails || {}, _b[constants_1.PERSISTENCE_MINIMAL_FLAG_CALLED_EVENTS] = response.minimalFlagCalledEvents === true, _b), (requestId ? (_c = {}, _c[constants_1.PERSISTENCE_FEATURE_FLAG_REQUEST_ID] = requestId, _c) : {})), (evaluatedAt ? (_d = {}, _d[constants_1.PERSISTENCE_FEATURE_FLAG_EVALUATED_AT] = evaluatedAt, _d) : {}));
};
exports.parseFlagsResponse = parseFlagsResponse;
var normalizeFlagsResponse = function (response, responseLogger) {
    var flagDetails = response['flags'];
    if (flagDetails) {
        // This is a /flags?v=2 request.
        // Map of flag keys to flag values: Record<string, string | boolean>
        var featureFlags = Object.fromEntries(Object.keys(flagDetails).map(function (flag) { var _a; return [flag, (_a = flagDetails[flag].variant) !== null && _a !== void 0 ? _a : flagDetails[flag].enabled]; }));
        // Map of flag keys to flag payloads: Record<string, JsonType>
        var featureFlagPayloads = Object.fromEntries(Object.keys(flagDetails)
            .filter(function (flag) { return flagDetails[flag].enabled; })
            .filter(function (flag) { var _a; return !(0, core_1.isUndefined)((_a = flagDetails[flag].metadata) === null || _a === void 0 ? void 0 : _a.payload); })
            .map(function (flag) { var _a; return [flag, (_a = flagDetails[flag].metadata) === null || _a === void 0 ? void 0 : _a.payload]; }));
        return __assign(__assign({}, response), { featureFlags: featureFlags, featureFlagPayloads: featureFlagPayloads });
    }
    else if (response['featureFlags']) {
        // The response has no `flags` key but does carry top-level `featureFlags`, which is the
        // shape returned by older servers that don't understand `?v=2`. A valid v2 response with no
        // flags (e.g. a project without any feature flags) legitimately omits `flags`, so we must
        // not warn in that case.
        responseLogger.warn('Using an older version of the feature flags endpoint. Please upgrade your PostHog server to the latest version');
    }
    return response;
};
exports.QuotaLimitedResource = {
    FeatureFlags: 'feature_flags',
    Recordings: 'recordings',
};
var PostHogFeatureFlags = /** @class */ (function () {
    function PostHogFeatureFlags(instanceOrConfigSource) {
        var _this = this;
        this.name = extension_tokens_1.FeatureFlagsExtension;
        this._override_warning = false;
        this.featureFlagEventHandlers = [];
        this._logger = logger;
        this._baseEventProperties = {};
        this._eventPropertiesWithFlagValues = {};
        this._reloadingHandlers = [];
        this._hasLoadedFlags = false;
        this._requestInFlight = false;
        this._requestGeneration = 0;
        this._reloadingDisabled = false;
        this._additionalReloadRequested = false;
        this._flagsLoadedFromRemote = false;
        this._staleCacheRefreshTriggered = false;
        this._consecutiveStatusZeroFailures = 0;
        this._onOnline = function () {
            var wasTripped = _this._hasStatusZeroCircuitBreakerTripped();
            _this._consecutiveStatusZeroFailures = 0;
            if (wasTripped) {
                _this.reloadFeatureFlags();
            }
        };
        this._refreshIfDue = function () {
            var _a;
            var refreshIntervalMs = _this._refreshIntervalMs;
            if ((0, core_1.isUndefined)(refreshIntervalMs) ||
                _this._config.remoteRequestsDisabled ||
                !globals_1.document ||
                globals_1.document.visibilityState === 'hidden' ||
                Date.now() - ((_a = _this._lastRefreshAt) !== null && _a !== void 0 ? _a : 0) < refreshIntervalMs) {
                return;
            }
            _this.reloadFeatureFlags();
            _this._scheduleNextRefresh();
        };
        this._onVisibilityChange = function () {
            if ((globals_1.document === null || globals_1.document === void 0 ? void 0 : globals_1.document.visibilityState) === 'visible') {
                _this._refreshIfDue();
            }
        };
        if ('get' in instanceOrConfigSource) {
            this._configSource = instanceOrConfigSource;
        }
        else {
            this._instance = instanceOrConfigSource;
            this._mutableConfigSource = new feature_flags_config_1.MutableFeatureFlagsConfigSource(instanceOrConfigSource.config, instanceOrConfigSource._shouldDisableFlags());
            this._configSource = this._mutableConfigSource;
        }
    }
    PostHogFeatureFlags.prototype.updateConfig = function (config, remoteRequestsDisabled) {
        var _a;
        (_a = this._mutableConfigSource) === null || _a === void 0 ? void 0 : _a.update(config, remoteRequestsDisabled);
        if (this._client) {
            this._syncAutomaticRefresh();
        }
    };
    PostHogFeatureFlags.prototype.setup = function (client) {
        var _this = this;
        this._initializingClient = client;
        this._logger = client.logger.createLogger('[FeatureFlags]');
        return (0, promise_utils_1.continueWith)(client.kv.initialize(), function () {
            if (_this._initializingClient !== client) {
                return;
            }
            _this._initializingClient = undefined;
            _this._client = client;
            _this._finishSetup(client);
        });
    };
    PostHogFeatureFlags.prototype._finishSetup = function (client) {
        var _this = this;
        var _a, _b;
        if (this._client !== client) {
            return;
        }
        if (globals_1.window) {
            (0, general_utils_1.addEventListener)(globals_1.window, 'online', this._onOnline);
        }
        this._syncAutomaticRefresh();
        this._dynamicProperties = client.registerDynamicEventProperties(function () {
            return _this._isCacheStale() ? _this._baseEventProperties : _this._eventPropertiesWithFlagValues;
        });
        this._crossTabPersistenceUnsubscribe = (_b = (_a = this._instance) === null || _a === void 0 ? void 0 : _a.persistence) === null || _b === void 0 ? void 0 : _b.onCrossTabFeatureFlagChange(function () {
            _this._rebuildEventProperties();
            _this._fireFeatureFlagsCallbacks();
        });
        this._rebuildEventProperties();
        return this.initialize();
    };
    PostHogFeatureFlags.prototype._syncAutomaticRefresh = function () {
        var configuredIntervalMs = this._config.refreshIntervalMs;
        var refreshIntervalMs = !this._config.remoteRequestsDisabled &&
            globals_1.document &&
            !(0, core_1.isUndefined)(configuredIntervalMs) &&
            configuredIntervalMs > 0
            ? configuredIntervalMs
            : undefined;
        if (refreshIntervalMs === this._refreshIntervalMs) {
            return;
        }
        this._stopAutomaticRefresh();
        if ((0, core_1.isUndefined)(refreshIntervalMs)) {
            return;
        }
        this._refreshIntervalMs = refreshIntervalMs;
        this._scheduleNextRefresh();
        if (globals_1.document === null || globals_1.document === void 0 ? void 0 : globals_1.document.addEventListener) {
            (0, general_utils_1.addEventListener)(globals_1.document, constants_1.DOM_EVENT_VISIBILITYCHANGE, this._onVisibilityChange);
        }
    };
    PostHogFeatureFlags.prototype._scheduleNextRefresh = function () {
        if ((0, core_1.isUndefined)(this._refreshIntervalMs)) {
            return;
        }
        if (!(0, core_1.isUndefined)(this._refreshInterval)) {
            clearInterval(this._refreshInterval);
        }
        this._lastRefreshAt = Date.now();
        this._refreshInterval = setInterval(this._refreshIfDue, this._refreshIntervalMs);
    };
    PostHogFeatureFlags.prototype._stopAutomaticRefresh = function () {
        var _a;
        if (!(0, core_1.isUndefined)(this._refreshInterval)) {
            clearInterval(this._refreshInterval);
            this._refreshInterval = undefined;
            (_a = globals_1.document === null || globals_1.document === void 0 ? void 0 : globals_1.document.removeEventListener) === null || _a === void 0 ? void 0 : _a.call(globals_1.document, constants_1.DOM_EVENT_VISIBILITYCHANGE, this._onVisibilityChange);
        }
        this._refreshIntervalMs = undefined;
        this._lastRefreshAt = undefined;
    };
    PostHogFeatureFlags.prototype.destroy = function () {
        this._dispose();
    };
    PostHogFeatureFlags.prototype.dispose = function () {
        this._dispose();
    };
    PostHogFeatureFlags.prototype._dispose = function () {
        var _a, _b;
        this._stopAutomaticRefresh();
        this._requestGeneration++;
        this._additionalReloadRequested = false;
        this._initializingClient = undefined;
        if (!this._client) {
            return;
        }
        this._clearDebouncer();
        (_a = this._dynamicProperties) === null || _a === void 0 ? void 0 : _a.dispose();
        this._dynamicProperties = undefined;
        (_b = this._crossTabPersistenceUnsubscribe) === null || _b === void 0 ? void 0 : _b.call(this);
        this._crossTabPersistenceUnsubscribe = undefined;
        this._reloadingHandlers = [];
        globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.removeEventListener('online', this._onOnline);
        this._client = undefined;
    };
    Object.defineProperty(PostHogFeatureFlags.prototype, "_config", {
        get: function () {
            return this._configSource.get();
        },
        enumerable: false,
        configurable: true
    });
    PostHogFeatureFlags.prototype._prop = function (key) {
        var _a;
        return (_a = this._client) === null || _a === void 0 ? void 0 : _a.kv.get(key);
    };
    PostHogFeatureFlags.prototype._set = function (properties) {
        var _this = this;
        this._persist(function () { var _a; return (_a = _this._client) === null || _a === void 0 ? void 0 : _a.kv.set(properties); });
    };
    PostHogFeatureFlags.prototype._markCrossTabFeatureFlagSnapshot = function (statePatch, response, partialResponse) {
        var _a, e_2, _b;
        var _c;
        if (!((_c = this._instance) === null || _c === void 0 ? void 0 : _c.persistence) || !statePatch[constants_1.ENABLED_FEATURE_FLAGS]) {
            return;
        }
        var previousFlags = this._prop(constants_1.ENABLED_FEATURE_FLAGS) || {};
        var nextFlags = statePatch[constants_1.ENABLED_FEATURE_FLAGS] || {};
        var responseFlags = response.flags || response.featureFlags;
        var successfulResponseFlagKeys = response.flags
            ? Object.entries(response.flags)
                .filter(function (_a) {
                var _b = __read(_a, 2), detail = _b[1];
                return !(detail === null || detail === void 0 ? void 0 : detail.failed);
            })
                .map(function (_a) {
                var _b = __read(_a, 1), key = _b[0];
                return key;
            })
            : [];
        var isIncompleteResponse = !!response.errorsWhileComputingFlags && !!response.flags;
        var ownedFlagKeys = isIncompleteResponse
            ? successfulResponseFlagKeys
            : partialResponse && !(0, core_1.isArray)(responseFlags)
                ? Object.keys(responseFlags || {})
                : Array.from(new Set(__spreadArray(__spreadArray([], __read(Object.keys(previousFlags)), false), __read(Object.keys(nextFlags)), false)));
        var previousPayloads = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_PAYLOADS) || {};
        var nextPayloads = statePatch[constants_1.PERSISTENCE_FEATURE_FLAG_PAYLOADS] || {};
        var ownedPayloadKeys = isIncompleteResponse || partialResponse
            ? ownedFlagKeys
            : Array.from(new Set(__spreadArray(__spreadArray([], __read(Object.keys(previousPayloads)), false), __read(Object.keys(nextPayloads)), false)));
        var ownsCompleteSnapshot = !isIncompleteResponse && !partialResponse;
        var flagOwnership = ownsCompleteSnapshot ? true : ownedFlagKeys;
        var payloadOwnership = ownsCompleteSnapshot ? true : ownedPayloadKeys;
        var changes = (_a = {},
            _a[constants_1.PERSISTENCE_ACTIVE_FEATURE_FLAGS] = flagOwnership,
            _a[constants_1.ENABLED_FEATURE_FLAGS] = flagOwnership,
            _a[constants_1.PERSISTENCE_FEATURE_FLAG_PAYLOADS] = payloadOwnership,
            _a);
        if (statePatch[constants_1.PERSISTENCE_FEATURE_FLAG_DETAILS]) {
            changes[constants_1.PERSISTENCE_FEATURE_FLAG_DETAILS] = flagOwnership;
        }
        try {
            for (var _d = __values([
                constants_1.PERSISTENCE_FEATURE_FLAG_REQUEST_ID,
                constants_1.PERSISTENCE_FEATURE_FLAG_EVALUATED_AT,
                constants_1.PERSISTENCE_MINIMAL_FLAG_CALLED_EVENTS,
            ]), _e = _d.next(); !_e.done; _e = _d.next()) {
                var key = _e.value;
                if (!(0, core_1.isUndefined)(statePatch[key])) {
                    changes[key] = true;
                }
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (_e && !_e.done && (_b = _d.return)) _b.call(_d);
            }
            finally { if (e_2) throw e_2.error; }
        }
        this._instance.persistence.markCrossTabFeatureFlagChanges(changes);
    };
    PostHogFeatureFlags.prototype._remove = function (keys) {
        var _this = this;
        this._persist(function () { var _a; return (_a = _this._client) === null || _a === void 0 ? void 0 : _a.kv.remove(keys); });
    };
    PostHogFeatureFlags.prototype._persist = function (operation) {
        try {
            operation();
        }
        catch (error) {
            this._logger.error('Failed to update feature flag persistence', error);
        }
    };
    PostHogFeatureFlags.prototype._rebuildEventProperties = function () {
        var e_3, _a, e_4, _b;
        var common = {};
        try {
            for (var _c = __values([
                constants_1.PERSISTENCE_ACTIVE_FEATURE_FLAGS,
                constants_1.PERSISTENCE_FEATURE_FLAG_PAYLOADS,
                constants_1.PERSISTENCE_FEATURE_FLAG_REQUEST_ID,
                constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS,
            ]), _d = _c.next(); !_d.done; _d = _c.next()) {
                var key = _d.value;
                var value = this._prop(key);
                if (!(0, core_1.isUndefined)(value)) {
                    common[key] = value;
                }
            }
        }
        catch (e_3_1) { e_3 = { error: e_3_1 }; }
        finally {
            try {
                if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
            }
            finally { if (e_3) throw e_3.error; }
        }
        this._baseEventProperties = common;
        var withFlagValues = __assign({}, common);
        var flags = this._prop(constants_1.ENABLED_FEATURE_FLAGS);
        if (flags) {
            try {
                for (var _e = __values(Object.entries(flags)), _f = _e.next(); !_f.done; _f = _e.next()) {
                    var _g = __read(_f.value, 2), key = _g[0], value = _g[1];
                    withFlagValues["$feature/".concat(key)] = value;
                }
            }
            catch (e_4_1) { e_4 = { error: e_4_1 }; }
            finally {
                try {
                    if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
                }
                finally { if (e_4) throw e_4.error; }
            }
        }
        this._eventPropertiesWithFlagValues = withFlagValues;
    };
    /**
     * Check if the feature flag cache is stale based on the configured TTL.
     */
    PostHogFeatureFlags.prototype._isCacheStale = function () {
        var ttl = this._config.cacheTtlMs;
        if (!ttl || ttl <= 0) {
            return false;
        }
        var evaluatedAt = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_EVALUATED_AT);
        return typeof evaluatedAt !== 'number' || Date.now() - evaluatedAt > ttl;
    };
    /**
     * Triggers a debounced reload when cache staleness is first detected.
     * Returns true if cache is stale, false otherwise.
     */
    PostHogFeatureFlags.prototype._checkAndTriggerStaleRefresh = function () {
        if (!this._isCacheStale()) {
            return false;
        }
        // Only trigger refresh once per stale period
        if (!this._staleCacheRefreshTriggered && !this._requestInFlight) {
            this._staleCacheRefreshTriggered = true;
            this._logger.warn('Feature flag cache is stale, triggering refresh...');
            this.reloadFeatureFlags();
        }
        return true;
    };
    PostHogFeatureFlags.prototype._getValidEvaluationEnvironments = function () {
        var _this = this;
        var envs = this._config.evaluationContexts;
        if (!(envs === null || envs === void 0 ? void 0 : envs.length)) {
            return [];
        }
        return envs.filter(function (env) {
            var isValid = env && typeof env === 'string' && env.trim().length > 0;
            if (!isValid) {
                _this._logger.error('Invalid evaluation context found:', env, 'Expected non-empty string');
            }
            return isValid;
        });
    };
    PostHogFeatureFlags.prototype._getValidFlagKeys = function () {
        var _this = this;
        var flagKeys = this._config.flagKeys;
        if ((0, core_1.isUndefined)(flagKeys)) {
            return undefined;
        }
        return flagKeys.filter(function (flagKey) {
            var isValid = flagKey && typeof flagKey === 'string' && flagKey.trim().length > 0;
            if (!isValid) {
                _this._logger.error('Invalid flag key found:', flagKey, 'Expected non-empty string');
            }
            return isValid;
        });
    };
    PostHogFeatureFlags.prototype.initialize = function () {
        var _a, _b, _c, _d;
        var config = this._config;
        var bootstrapFlags = (_b = (_a = config.bootstrap) === null || _a === void 0 ? void 0 : _a.featureFlags) !== null && _b !== void 0 ? _b : {};
        var hasBootstrappedFlags = Object.keys(bootstrapFlags).length;
        if (hasBootstrappedFlags) {
            var bootstrapPayloads_1 = (_d = (_c = config.bootstrap) === null || _c === void 0 ? void 0 : _c.featureFlagPayloads) !== null && _d !== void 0 ? _d : {};
            var activeFlags_1 = Object.keys(bootstrapFlags)
                .filter(function (flag) { return !!bootstrapFlags[flag]; })
                .reduce(function (res, key) {
                res[key] = bootstrapFlags[key] || false;
                return res;
            }, {});
            var featureFlagPayloads = Object.keys(bootstrapPayloads_1)
                .filter(function (key) { return activeFlags_1[key]; })
                .reduce(function (res, key) {
                res[key] = bootstrapPayloads_1[key];
                return res;
            }, {});
            return this._receivedFeatureFlags({ featureFlags: activeFlags_1, featureFlagPayloads: featureFlagPayloads });
        }
        return undefined;
    };
    PostHogFeatureFlags.prototype.updateFlags = function (flags, payloads, options) {
        var e_5, _a;
        var _b, _c;
        // Merge against the raw stored flags/payloads, not the override-applied getters.
        var existingFlags = (options === null || options === void 0 ? void 0 : options.merge)
            ? ((_b = this._prop(constants_1.ENABLED_FEATURE_FLAGS)) !== null && _b !== void 0 ? _b : {})
            : {};
        var existingPayloads = (options === null || options === void 0 ? void 0 : options.merge)
            ? ((_c = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_PAYLOADS)) !== null && _c !== void 0 ? _c : {})
            : {};
        var finalFlags = __assign(__assign({}, existingFlags), flags);
        var finalPayloads = __assign(__assign({}, existingPayloads), payloads);
        // Convert simple flags to v4 format to avoid deprecation warning
        var flagDetails = {};
        try {
            for (var _d = __values(Object.entries(finalFlags)), _e = _d.next(); !_e.done; _e = _d.next()) {
                var _f = __read(_e.value, 2), key = _f[0], value = _f[1];
                flagDetails[key] = {
                    key: key,
                    enabled: (0, core_1.getEnabledFromValue)(value),
                    variant: (0, core_1.getVariantFromValue)(value),
                    reason: undefined,
                    // id: 0 indicates manually injected flags (not from server evaluation)
                    metadata: !(0, core_1.isUndefined)(finalPayloads === null || finalPayloads === void 0 ? void 0 : finalPayloads[key])
                        ? { id: 0, version: undefined, description: undefined, payload: finalPayloads[key] }
                        : undefined,
                };
            }
        }
        catch (e_5_1) { e_5 = { error: e_5_1 }; }
        finally {
            try {
                if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
            }
            finally { if (e_5) throw e_5.error; }
        }
        void this._receivedFeatureFlags({
            flags: flagDetails,
        });
    };
    Object.defineProperty(PostHogFeatureFlags.prototype, "hasLoadedFlags", {
        get: function () {
            return this._hasLoadedFlags;
        },
        enumerable: false,
        configurable: true
    });
    PostHogFeatureFlags.prototype.getFlags = function () {
        return Object.keys(this.getFlagVariants());
    };
    PostHogFeatureFlags.prototype.getFlagsWithDetails = function () {
        var e_6, _a;
        var _b, _c;
        var flagDetails = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_DETAILS);
        var overridenFlags = this._prop(constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS);
        var overriddenPayloads = this._prop(constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS);
        if (!overriddenPayloads && !overridenFlags) {
            return flagDetails || {};
        }
        var finalDetails = (0, general_utils_1.extend)({}, flagDetails || {});
        var overriddenKeys = __spreadArray([], __read(new Set(__spreadArray(__spreadArray([], __read(Object.keys(overriddenPayloads || {})), false), __read(Object.keys(overridenFlags || {})), false))), false);
        try {
            for (var overriddenKeys_1 = __values(overriddenKeys), overriddenKeys_1_1 = overriddenKeys_1.next(); !overriddenKeys_1_1.done; overriddenKeys_1_1 = overriddenKeys_1.next()) {
                var key = overriddenKeys_1_1.value;
                var originalDetail = finalDetails[key];
                var overrideFlagValue = overridenFlags === null || overridenFlags === void 0 ? void 0 : overridenFlags[key];
                var finalEnabled = (0, core_1.isUndefined)(overrideFlagValue)
                    ? ((_b = originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.enabled) !== null && _b !== void 0 ? _b : false)
                    : !!overrideFlagValue;
                var overrideVariant = (0, core_1.isUndefined)(overrideFlagValue)
                    ? originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.variant
                    : typeof overrideFlagValue === 'string'
                        ? overrideFlagValue
                        : undefined;
                var overridePayload = overriddenPayloads === null || overriddenPayloads === void 0 ? void 0 : overriddenPayloads[key];
                var overridenDetail = __assign(__assign({}, originalDetail), { enabled: finalEnabled, 
                    // If the flag is not enabled, the variant should be undefined, even if the original has a variant value.
                    variant: finalEnabled ? (overrideVariant !== null && overrideVariant !== void 0 ? overrideVariant : originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.variant) : undefined });
                // Keep track of the original enabled and variant values so we can send them in the $feature_flag_called event.
                // This will be helpful for debugging and for understanding the impact of overrides.
                if (finalEnabled !== (originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.enabled)) {
                    overridenDetail.original_enabled = originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.enabled;
                }
                if (overrideVariant !== (originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.variant)) {
                    overridenDetail.original_variant = originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.variant;
                }
                if (overridePayload) {
                    overridenDetail.metadata = __assign(__assign({}, originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.metadata), { payload: overridePayload, original_payload: (_c = originalDetail === null || originalDetail === void 0 ? void 0 : originalDetail.metadata) === null || _c === void 0 ? void 0 : _c.payload });
                }
                finalDetails[key] = overridenDetail;
            }
        }
        catch (e_6_1) { e_6 = { error: e_6_1 }; }
        finally {
            try {
                if (overriddenKeys_1_1 && !overriddenKeys_1_1.done && (_a = overriddenKeys_1.return)) _a.call(overriddenKeys_1);
            }
            finally { if (e_6) throw e_6.error; }
        }
        if (!this._override_warning) {
            this._logger.warn(' Overriding feature flag details!', {
                flagDetails: flagDetails,
                overriddenPayloads: overriddenPayloads,
                finalDetails: finalDetails,
            });
            this._override_warning = true;
        }
        return finalDetails;
    };
    PostHogFeatureFlags.prototype.getAllFeatureFlags = function () {
        var flagVariants = this.getFlagVariants();
        var payloads = this.getFlagPayloads();
        return Object.keys(flagVariants).map(function (key) {
            var flagValue = flagVariants[key];
            return {
                key: key,
                enabled: (0, core_1.getEnabledFromValue)(flagValue),
                variant: (0, core_1.getVariantFromValue)(flagValue),
                payload: (0, core_1.parsePayload)(payloads[key]),
            };
        });
    };
    PostHogFeatureFlags.prototype.getFlagVariants = function () {
        var enabledFlags = this._prop(constants_1.ENABLED_FEATURE_FLAGS);
        var overriddenFlags = this._prop(constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS);
        if (!overriddenFlags) {
            return enabledFlags || {};
        }
        var finalFlags = (0, general_utils_1.extend)({}, enabledFlags || {});
        var overriddenKeys = Object.keys(overriddenFlags);
        for (var i = 0; i < overriddenKeys.length; i++) {
            finalFlags[overriddenKeys[i]] = overriddenFlags[overriddenKeys[i]];
        }
        if (!this._override_warning) {
            this._logger.warn(' Overriding feature flags!', {
                enabledFlags: enabledFlags,
                overriddenFlags: overriddenFlags,
                finalFlags: finalFlags,
            });
            this._override_warning = true;
        }
        return finalFlags;
    };
    PostHogFeatureFlags.prototype.getFlagPayloads = function () {
        var flagPayloads = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_PAYLOADS);
        var overriddenPayloads = this._prop(constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS);
        if (!overriddenPayloads) {
            return flagPayloads || {};
        }
        var finalPayloads = (0, general_utils_1.extend)({}, flagPayloads || {});
        var overriddenKeys = Object.keys(overriddenPayloads);
        for (var i = 0; i < overriddenKeys.length; i++) {
            finalPayloads[overriddenKeys[i]] = overriddenPayloads[overriddenKeys[i]];
        }
        if (!this._override_warning) {
            this._logger.warn(' Overriding feature flag payloads!', {
                flagPayloads: flagPayloads,
                overriddenPayloads: overriddenPayloads,
                finalPayloads: finalPayloads,
            });
            this._override_warning = true;
        }
        return finalPayloads;
    };
    /**
     * Reloads feature flags asynchronously.
     *
     * Constraints:
     *
     * 1. Avoid parallel requests
     * 2. Delay a few milliseconds after each reloadFeatureFlags call to batch subsequent changes together
     */
    PostHogFeatureFlags.prototype.reloadFeatureFlags = function () {
        var _this = this;
        if (this._reloadingDisabled || this._config.featureFlagsDisabled) {
            // If reloading has been explicitly disabled then we don't want to do anything
            // Or if feature flags are disabled
            return;
        }
        if (this._hasStatusZeroCircuitBreakerTripped()) {
            return;
        }
        if (this._reloadDebouncer) {
            // If we're already in a debounce then we don't want to do anything
            return;
        }
        // Notify browser-v1 facade listeners before the debounced request starts.
        this._reloadingHandlers.slice().forEach(function (handler) {
            try {
                handler();
            }
            catch (error) {
                _this._logger.error('Error while running feature flags reloading callback', error);
            }
        });
        // Debounce multiple calls on the same tick
        this._reloadDebouncer = setTimeout(function () {
            _this._callFlagsEndpoint();
        }, 5);
    };
    PostHogFeatureFlags.prototype._clearDebouncer = function () {
        clearTimeout(this._reloadDebouncer);
        this._reloadDebouncer = undefined;
    };
    PostHogFeatureFlags.prototype.onReloading = function (handler) {
        var _this = this;
        this._reloadingHandlers.push(handler);
        return function () {
            _this._reloadingHandlers = _this._reloadingHandlers.filter(function (entry) { return entry !== handler; });
        };
    };
    PostHogFeatureFlags.prototype.ensureFlagsLoaded = function () {
        if (this._hasLoadedFlags || this._requestInFlight || this._reloadDebouncer) {
            // If we are or have already loaded the flags then we don't want to do anything
            return;
        }
        this.reloadFeatureFlags();
    };
    PostHogFeatureFlags.prototype.setAnonymousDistinctId = function (anon_distinct_id) {
        this.$anon_distinct_id = anon_distinct_id;
    };
    PostHogFeatureFlags.prototype.setReloadingPaused = function (isPaused) {
        this._reloadingDisabled = isPaused;
    };
    PostHogFeatureFlags.prototype.resetFlagCallReported = function () {
        this._remove(constants_1.FLAG_CALL_REPORTED);
    };
    PostHogFeatureFlags.prototype._callFlagsEndpoint = function (options) {
        var _this = this;
        this._clearDebouncer();
        var client = this._client;
        if (!client || this._config.remoteRequestsDisabled || this._hasStatusZeroCircuitBreakerTripped()) {
            return;
        }
        if (this._requestInFlight) {
            this._additionalReloadRequested = true;
            return;
        }
        var data = {
            token: client.projectToken,
            distinct_id: client.distinctId,
            groups: client.groups,
            $anon_distinct_id: this.$anon_distinct_id,
            person_properties: __assign(__assign(__assign({}, client.initialPersonProperties), (this._prop(constants_1.STORED_PERSON_PROPERTIES_KEY) || {})), { $lib: client.library.name, $lib_version: client.library.version }),
            group_properties: this._prop(constants_1.STORED_GROUP_PROPERTIES_KEY),
            timezone: (0, event_utils_1.getTimezone)(),
        };
        if (!(0, core_1.isUndefined)(client.deviceId)) {
            data.$device_id = client.deviceId;
        }
        if ((options === null || options === void 0 ? void 0 : options.disableFlags) || this._config.featureFlagsDisabled) {
            data.disable_flags = true;
        }
        var evaluationContexts = this._getValidEvaluationEnvironments();
        if (evaluationContexts.length) {
            data.evaluation_contexts = evaluationContexts;
        }
        var flagKeys = this._getValidFlagKeys();
        if (!(0, core_1.isUndefined)(flagKeys)) {
            data.flag_keys = flagKeys;
        }
        var isPartialFlagsResponse = this._config.onlyEvaluateSurveyFeatureFlags;
        var path = "/flags/?v=2".concat(isPartialFlagsResponse ? '&only_evaluate_survey_feature_flags=true' : '');
        var requestGeneration = this._requestGeneration;
        this._requestInFlight = true;
        var requestAdditionalReload = function () {
            if (_this._additionalReloadRequested) {
                _this._additionalReloadRequested = false;
                _this._callFlagsEndpoint();
            }
        };
        var handleResponse = function (response) {
            var _a;
            var _b, _c;
            var json = ((_b = response.json) !== null && _b !== void 0 ? _b : {});
            var errorsLoading = response.statusCode !== 200;
            _this._requestInFlight = false;
            if (requestGeneration !== _this._requestGeneration) {
                requestAdditionalReload();
                return;
            }
            _this._trackStatusZeroReachability(response.statusCode);
            if (!errorsLoading && !_this._additionalReloadRequested) {
                _this.$anon_distinct_id = undefined;
            }
            if (data.disable_flags && !_this._additionalReloadRequested) {
                return;
            }
            _this._flagsLoadedFromRemote = !errorsLoading;
            var flagErrors = [];
            if (response.error) {
                flagErrors.push(response.error instanceof Error && response.error.name === 'AbortError'
                    ? exports.FeatureFlagError.TIMEOUT
                    : response.error instanceof Error
                        ? exports.FeatureFlagError.CONNECTION_ERROR
                        : exports.FeatureFlagError.UNKNOWN_ERROR);
            }
            else if (response.statusCode !== 200) {
                flagErrors.push(exports.FeatureFlagError.apiError(response.statusCode));
            }
            if (json.errorsWhileComputingFlags) {
                flagErrors.push(exports.FeatureFlagError.ERRORS_WHILE_COMPUTING);
            }
            var isQuotaLimited = !!((_c = json.quotaLimited) === null || _c === void 0 ? void 0 : _c.includes(exports.QuotaLimitedResource.FeatureFlags));
            if (isQuotaLimited) {
                flagErrors.push(exports.FeatureFlagError.QUOTA_LIMITED);
            }
            _this._set((_a = {}, _a[constants_1.PERSISTENCE_FEATURE_FLAG_ERRORS] = flagErrors, _a));
            if (isQuotaLimited) {
                _this._logger.warn('You have hit your feature flags quota limit, and will not be able to load feature flags until the quota is reset.  Please visit https://posthog.com/docs/billing/limits-alerts to learn more.');
            }
            else if (!data.disable_flags) {
                _this._receivedFeatureFlags(json, errorsLoading, { partialResponse: isPartialFlagsResponse });
            }
            requestAdditionalReload();
        };
        var handleError = function (error) {
            var _a;
            _this._requestInFlight = false;
            if (requestGeneration !== _this._requestGeneration) {
                requestAdditionalReload();
                return;
            }
            _this._set((_a = {}, _a[constants_1.PERSISTENCE_FEATURE_FLAG_ERRORS] = [exports.FeatureFlagError.CONNECTION_ERROR], _a));
            _this._logger.error('Feature flag request failed', error);
            requestAdditionalReload();
        };
        try {
            void client
                .sendRequest(path, {
                target: 'flags',
                method: 'POST',
                body: data,
                compression: this._config.compression,
                sentAt: 'body',
                timeoutMs: this._config.requestTimeoutMs,
            })
                .then(handleResponse)
                .catch(handleError);
        }
        catch (error) {
            handleError(error);
        }
    };
    PostHogFeatureFlags.prototype._hasStatusZeroCircuitBreakerTripped = function () {
        return (0, request_utils_1.isStatusZeroFailureCircuitBreakerTripped)(this._consecutiveStatusZeroFailures, MAX_CONSECUTIVE_FLAGS_STATUS_ZERO_FAILURES);
    };
    PostHogFeatureFlags.prototype._trackStatusZeroReachability = function (statusCode) {
        var _this = this;
        this._consecutiveStatusZeroFailures = (0, request_utils_1.updateStatusZeroFailureCount)(statusCode, this._consecutiveStatusZeroFailures, MAX_CONSECUTIVE_FLAGS_STATUS_ZERO_FAILURES, function () {
            return _this._logger.warn('Feature flag requests are failing before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped refreshing feature flags; will try again when connectivity changes.');
        });
    };
    /**
     * Get feature flag's value for user.
     *
     * By default, this method may return cached values from localStorage if the `/flags` endpoint
     * hasn't responded yet. This reduces flicker but means you might briefly see stale values
     * (e.g., a flag that was disabled on the server).
     *
     * ### Usage:
     *
     *     if(posthog.getFeatureFlag('my-flag') === 'some-variant') { // do something }
     *
     *     // Only use fresh values from the server (returns undefined until /flags responds)
     *     if(posthog.getFeatureFlag('my-flag', { fresh: true }) === 'some-variant') { // do something }
     *
     * @param {String} key Key of the feature flag.
     * @param {Object} options Optional settings.
     * @param {boolean} [options.send_event=true] If false, won't send a $feature_flag_called event to PostHog.
     * @param {boolean} [options.fresh=false] If true, only returns values loaded from the server, not cached localStorage values.
     *                  Use this when you need to ensure the flag value reflects the current server state,
     *                  such as after disabling a flag. Returns undefined until the /flags endpoint responds.
     * @returns {boolean | string | undefined} The flag value, or undefined if not found or not yet loaded.
     */
    PostHogFeatureFlags.prototype.getFeatureFlag = function (key, options) {
        var _a;
        if (options === void 0) { options = {}; }
        if (options.fresh && !this._flagsLoadedFromRemote) {
            return undefined;
        }
        if (!this._hasLoadedFlags && !(this.getFlags() && this.getFlags().length > 0)) {
            this._logger.warn('getFeatureFlag for key "' + key + FLAG_TIMEOUT_MSG);
            return undefined;
        }
        // Check if cache is stale and trigger refresh if needed
        if (this._checkAndTriggerStaleRefresh()) {
            return undefined;
        }
        var result = this.getFeatureFlagResult(key, options);
        return (_a = result === null || result === void 0 ? void 0 : result.variant) !== null && _a !== void 0 ? _a : result === null || result === void 0 ? void 0 : result.enabled;
    };
    /*
     * Retrieves the details for a feature flag.
     *
     * ### Usage:
     *
     *     const details = getFeatureFlagDetails("my-flag")
     *     console.log(details.metadata.version)
     *     console.log(details.reason)
     *
     * @param {String} key Key of the feature flag.
     */
    PostHogFeatureFlags.prototype.getFeatureFlagDetails = function (key) {
        var details = this.getFlagsWithDetails();
        return details[key];
    };
    /**
     * @deprecated Use `getFeatureFlagResult()` instead which properly tracks the feature flag call.
     * `getFeatureFlagPayload()` does not emit the `$feature_flag_called` event which may result in
     * missing analytics. This method will be removed in a future version.
     */
    PostHogFeatureFlags.prototype.getFeatureFlagPayload = function (key) {
        // Don't send event to maintain backwards compatibility - this method never tracked calls
        var result = this.getFeatureFlagResult(key, { send_event: false });
        return result === null || result === void 0 ? void 0 : result.payload;
    };
    /**
     * Get a feature flag result including both the flag value and payload, while properly tracking the call.
     * This method emits the `$feature_flag_called` event by default.
     *
     * By default, this method may return cached values from localStorage if the `/flags` endpoint
     * hasn't responded yet. This reduces flicker but means you might briefly see stale values
     * (e.g., a flag that was disabled on the server).
     *
     * ### Usage:
     *
     *     const result = posthog.getFeatureFlagResult('my-flag')
     *     if (result?.enabled) {
     *         console.log('Flag is enabled with payload:', result.payload)
     *     }
     *
     *     // Only use fresh values from the server
     *     const freshResult = posthog.getFeatureFlagResult('my-flag', { fresh: true })
     *
     * @param {String} key Key of the feature flag.
     * @param {Object} [options] Options for the feature flag lookup.
     * @param {boolean} [options.send_event=true] If false, won't send the $feature_flag_called event.
     * @param {boolean} [options.fresh=false] If true, only returns values loaded from the server, not cached localStorage values.
     *                  Use this when you need to ensure the flag value reflects the current server state.
     *                  Returns undefined until the /flags endpoint responds.
     * @returns {FeatureFlagResult | undefined} The feature flag result including key, enabled, variant, and payload.
     */
    PostHogFeatureFlags.prototype.getFeatureFlagResult = function (key, options) {
        var _a, _b, _c, _d;
        var _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
        if (options === void 0) { options = {}; }
        if (options.fresh && !this._flagsLoadedFromRemote) {
            return undefined;
        }
        if (!this._hasLoadedFlags && !(this.getFlags() && this.getFlags().length > 0)) {
            this._logger.warn('getFeatureFlagResult for key "' + key + FLAG_TIMEOUT_MSG);
            return undefined;
        }
        // Check if cache is stale and trigger refresh if needed
        if (this._checkAndTriggerStaleRefresh()) {
            return undefined;
        }
        var flagVariants = this.getFlagVariants();
        var flagExists = key in flagVariants;
        var flagValue = flagVariants[key];
        var payloads = this.getFlagPayloads();
        var payload = payloads[key];
        var flagReportValue = String(flagValue);
        var requestId = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_REQUEST_ID) || undefined;
        var evaluatedAt = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_EVALUATED_AT) || undefined;
        var flagCallReported = this._prop(constants_1.FLAG_CALL_REPORTED) || {};
        var sessionIdToPersist;
        // When session-scoped dedup is enabled, reset the reported flags whenever the session changes.
        if (this._config.deduplicateCallsPerSession) {
            var currentSessionId = (_e = this._client) === null || _e === void 0 ? void 0 : _e.session.sessionId;
            var storedSessionId = this._prop(constants_1.FLAG_CALL_REPORTED_SESSION_ID);
            if (currentSessionId && currentSessionId !== storedSessionId) {
                flagCallReported = {};
                sessionIdToPersist = currentSessionId;
            }
        }
        if (options.send_event || !('send_event' in options)) {
            if (!(key in flagCallReported) || !flagCallReported[key].includes(flagReportValue)) {
                if ((0, core_1.isArray)(flagCallReported[key])) {
                    flagCallReported[key].push(flagReportValue);
                }
                else {
                    flagCallReported[key] = [flagReportValue];
                }
                this._set(__assign((_a = {}, _a[constants_1.FLAG_CALL_REPORTED] = flagCallReported, _a), (sessionIdToPersist ? (_b = {}, _b[constants_1.FLAG_CALL_REPORTED_SESSION_ID] = sessionIdToPersist, _b) : {})));
                var flagDetails = this.getFeatureFlagDetails(key);
                var errors = __spreadArray([], __read(((_f = this._prop(constants_1.PERSISTENCE_FEATURE_FLAG_ERRORS)) !== null && _f !== void 0 ? _f : [])), false);
                if ((0, core_1.isUndefined)(flagValue)) {
                    errors.push(exports.FeatureFlagError.FLAG_MISSING);
                }
                var properties = {
                    $feature_flag: key,
                    $feature_flag_response: flagValue,
                    $feature_flag_payload: payload !== null && payload !== void 0 ? payload : null,
                    $feature_flag_request_id: requestId,
                    $feature_flag_evaluated_at: evaluatedAt,
                    $feature_flag_bootstrapped_response: (_j = (_h = (_g = this._config.bootstrap) === null || _g === void 0 ? void 0 : _g.featureFlags) === null || _h === void 0 ? void 0 : _h[key]) !== null && _j !== void 0 ? _j : null,
                    $feature_flag_bootstrapped_payload: (_m = (_l = (_k = this._config.bootstrap) === null || _k === void 0 ? void 0 : _k.featureFlagPayloads) === null || _l === void 0 ? void 0 : _l[key]) !== null && _m !== void 0 ? _m : null,
                    // If we haven't yet received a response from the /flags endpoint, we must have used the bootstrapped value
                    $used_bootstrap_value: !this._flagsLoadedFromRemote,
                };
                if (!(0, core_1.isUndefined)((_o = flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.metadata) === null || _o === void 0 ? void 0 : _o.has_experiment)) {
                    properties.$feature_flag_has_experiment = flagDetails.metadata.has_experiment;
                }
                if (!(0, core_1.isUndefined)((_p = flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.metadata) === null || _p === void 0 ? void 0 : _p.version)) {
                    properties.$feature_flag_version = flagDetails.metadata.version;
                }
                var reason = (_r = (_q = flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.reason) === null || _q === void 0 ? void 0 : _q.description) !== null && _r !== void 0 ? _r : (_s = flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.reason) === null || _s === void 0 ? void 0 : _s.code;
                if (reason) {
                    properties.$feature_flag_reason = reason;
                }
                if ((_t = flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.metadata) === null || _t === void 0 ? void 0 : _t.id) {
                    properties.$feature_flag_id = flagDetails.metadata.id;
                }
                // It's possible that flag values were overridden by calling overrideFeatureFlags.
                // We want to capture the original values in case someone forgets they were using overrides
                // and is wondering why their app is acting weird.
                if (!(0, core_1.isUndefined)(flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.original_variant) || !(0, core_1.isUndefined)(flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.original_enabled)) {
                    properties.$feature_flag_original_response = !(0, core_1.isUndefined)(flagDetails.original_variant)
                        ? flagDetails.original_variant
                        : flagDetails.original_enabled;
                }
                if ((_u = flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.metadata) === null || _u === void 0 ? void 0 : _u.original_payload) {
                    properties.$feature_flag_original_payload = (_v = flagDetails === null || flagDetails === void 0 ? void 0 : flagDetails.metadata) === null || _v === void 0 ? void 0 : _v.original_payload;
                }
                if (errors.length) {
                    properties.$feature_flag_error = errors.join(',');
                }
                this._captureFeatureFlagCalled(properties);
            }
            else if (sessionIdToPersist) {
                this._set((_c = {},
                    _c[constants_1.FLAG_CALL_REPORTED] = flagCallReported,
                    _c[constants_1.FLAG_CALL_REPORTED_SESSION_ID] = sessionIdToPersist,
                    _c));
            }
        }
        else if (sessionIdToPersist) {
            this._set((_d = {},
                _d[constants_1.FLAG_CALL_REPORTED] = flagCallReported,
                _d[constants_1.FLAG_CALL_REPORTED_SESSION_ID] = sessionIdToPersist,
                _d));
        }
        if (!flagExists) {
            return undefined;
        }
        return {
            key: key,
            enabled: !!flagValue,
            variant: typeof flagValue === 'string' ? flagValue : undefined,
            payload: (0, core_1.parsePayload)(payload),
        };
    };
    PostHogFeatureFlags.prototype._captureFeatureFlagCalled = function (properties) {
        var _this = this;
        var _a;
        try {
            void ((_a = this._client) === null || _a === void 0 ? void 0 : _a.capture('$feature_flag_called', properties).catch(function (error) {
                _this._logger.error('Failed to capture feature flag call', error);
            }));
        }
        catch (error) {
            this._logger.error('Failed to capture feature flag call', error);
        }
    };
    /*
     * Fetches the payload for a remote config feature flag. This method will bypass any cached values and fetch the latest
     * value from the PostHog API.
     *
     * Note: Because the posthog-js SDK is primarily used with public project API keys, encrypted remote config payloads will
     * be redacted, never decrypted in the response.
     *
     * ### Usage:
     *
     *     getRemoteConfigPayload("home-page-welcome-message", (payload) => console.log(`Fetched remote config: ${payload}`))
     *
     * @param {String} key Key of the feature flag.
     * @param {Function} [callback] The callback function will be called once the remote config feature flag payload has been fetched.
     */
    PostHogFeatureFlags.prototype.getRemoteConfigPayload = function (key, callback) {
        void this._getRemoteConfigPayload(key, callback);
    };
    PostHogFeatureFlags.prototype._getRemoteConfigPayload = function (key, callback) {
        return __awaiter(this, void 0, void 0, function () {
            var client, data, evaluationContexts, flagKeys, payload, response, payloads, error_1;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        client = this._client;
                        if (!client) {
                            return [2 /*return*/];
                        }
                        data = {
                            distinct_id: client.distinctId,
                            token: client.projectToken,
                            person_properties: { $lib: client.library.name, $lib_version: client.library.version },
                        };
                        evaluationContexts = this._getValidEvaluationEnvironments();
                        if (evaluationContexts.length) {
                            data.evaluation_contexts = evaluationContexts;
                        }
                        flagKeys = this._getValidFlagKeys();
                        if (!(0, core_1.isUndefined)(flagKeys)) {
                            data.flag_keys = flagKeys;
                        }
                        _b.label = 1;
                    case 1:
                        _b.trys.push([1, 3, , 4]);
                        return [4 /*yield*/, client.sendRequest('/flags/?v=2', {
                                target: 'flags',
                                method: 'POST',
                                body: data,
                                compression: this._config.compression,
                                sentAt: 'body',
                                timeoutMs: this._config.requestTimeoutMs,
                            })];
                    case 2:
                        response = _b.sent();
                        payloads = (_a = response.json) === null || _a === void 0 ? void 0 : _a.featureFlagPayloads;
                        payload = (payloads === null || payloads === void 0 ? void 0 : payloads[key]) || undefined;
                        return [3 /*break*/, 4];
                    case 3:
                        error_1 = _b.sent();
                        this._logger.error('Remote config feature flag request failed', error_1);
                        return [2 /*return*/];
                    case 4:
                        try {
                            callback(payload);
                        }
                        catch (error) {
                            this._logger.error('Remote config feature flag callback failed', error);
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    PostHogFeatureFlags.prototype.isFeatureEnabled = function (key, options) {
        if (options === void 0) { options = {}; }
        if (options.fresh && !this._flagsLoadedFromRemote) {
            return options.defaultValue;
        }
        if (!this._hasLoadedFlags && !(this.getFlags() && this.getFlags().length > 0)) {
            this._logger.warn('isFeatureEnabled for key "' + key + FLAG_TIMEOUT_MSG);
            return options.defaultValue;
        }
        var flagValue = this.getFeatureFlag(key, options);
        return (0, core_1.isUndefined)(flagValue) ? options.defaultValue : !!flagValue;
    };
    PostHogFeatureFlags.prototype.addFeatureFlagsHandler = function (handler) {
        this.featureFlagEventHandlers.push(handler);
    };
    PostHogFeatureFlags.prototype.removeFeatureFlagsHandler = function (handler) {
        this.featureFlagEventHandlers = this.featureFlagEventHandlers.filter(function (h) { return h !== handler; });
    };
    PostHogFeatureFlags.prototype.receivedFeatureFlags = function (response, errorsLoading, options) {
        void this._receivedFeatureFlags(response, errorsLoading, options);
    };
    PostHogFeatureFlags.prototype._receivedFeatureFlags = function (response, errorsLoading, options) {
        if (!this._client) {
            return;
        }
        this._hasLoadedFlags = true;
        var currentFlags = this.getFlagVariants();
        var currentFlagPayloads = this.getFlagPayloads();
        var currentFlagDetails = this.getFlagsWithDetails();
        var statePatch = (0, exports.parseFlagsResponse)(response, currentFlags, currentFlagPayloads, currentFlagDetails, options, this._logger);
        if (statePatch) {
            this._markCrossTabFeatureFlagSnapshot(statePatch, response, !!(options === null || options === void 0 ? void 0 : options.partialResponse));
            this._set(statePatch);
        }
        // Reset stale refresh flag when we successfully receive fresh flags
        if (!errorsLoading) {
            this._staleCacheRefreshTriggered = false;
        }
        this._fireFeatureFlagsCallbacks(errorsLoading);
    };
    /**
     * @deprecated Use overrideFeatureFlags instead. This will be removed in a future version.
     */
    PostHogFeatureFlags.prototype.override = function (flags, suppressWarning) {
        if (suppressWarning === void 0) { suppressWarning = false; }
        this._logger.warn('override is deprecated. Please use overrideFeatureFlags instead.');
        this.overrideFeatureFlags({
            flags: flags,
            suppressWarning: suppressWarning,
        });
    };
    /**
     * Override feature flags on the client-side. Useful for setting non-persistent feature flags,
     * or for testing/debugging feature flags in the PostHog app.
     *
     * ### Usage:
     *
     *     - posthog.featureFlags.overrideFeatureFlags(false) // clear all overrides
     *     - posthog.featureFlags.overrideFeatureFlags(['beta-feature']) // enable flags
     *     - posthog.featureFlags.overrideFeatureFlags({'beta-feature': 'variant'}) // set variants
     *     - posthog.featureFlags.overrideFeatureFlags({ flags: ['beta-feature'] }) // enable flags
     *     - posthog.featureFlags.overrideFeatureFlags({ flags: {'beta-feature': 'variant'} }) // set variants
     *     - posthog.featureFlags.overrideFeatureFlags({ // set both flags and payloads
     *         flags: {'beta-feature': 'variant'},
     *         payloads: { 'beta-feature': { someData: true } }
     *       })
     *     - posthog.featureFlags.overrideFeatureFlags({ // only override payloads
     *         payloads: { 'beta-feature': { someData: true } }
     *       })
     */
    PostHogFeatureFlags.prototype.overrideFeatureFlags = function (overrideOptions) {
        this._overrideFeatureFlags(overrideOptions);
    };
    PostHogFeatureFlags.prototype._overrideFeatureFlags = function (overrideOptions) {
        var _a, _b;
        var _c;
        if (!this._client) {
            this._logger.warn('posthog.featureFlags.overrideFeatureFlags called before feature flags were ready');
            return;
        }
        // Clear all overrides if false, lets you do something like posthog.featureFlags.overrideFeatureFlags(false)
        if (overrideOptions === false) {
            this._remove([constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS, constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS]);
            this._fireFeatureFlagsCallbacks();
            forceDebugLogger.info('All overrides cleared');
            return;
        }
        // Array syntax: ['flag-a', 'flag-b'] -> { 'flag-a': true, 'flag-b': true }
        if ((0, core_1.isArray)(overrideOptions)) {
            this._set((_a = {}, _a[constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS] = arrayToFlagsRecord(overrideOptions), _a));
            this._fireFeatureFlagsCallbacks();
            forceDebugLogger.info('Flag overrides set', { flags: overrideOptions });
            return;
        }
        if (overrideOptions &&
            typeof overrideOptions === 'object' &&
            ('flags' in overrideOptions || 'payloads' in overrideOptions)) {
            var options = overrideOptions;
            this._override_warning = Boolean((_c = options.suppressWarning) !== null && _c !== void 0 ? _c : false);
            var statePatch = {};
            var flags = options.flags;
            var payloads = options.payloads;
            // Handle flags if provided, lets you do something like posthog.featureFlags.overrideFeatureFlags({flags: ['beta-feature']})
            if (flags) {
                statePatch[constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS] = (0, core_1.isArray)(flags) ? arrayToFlagsRecord(flags) : flags;
            }
            // Handle payloads independently, lets you do something like posthog.featureFlags.overrideFeatureFlags({payloads: { 'beta-feature': { someData: true } }})
            if (payloads) {
                statePatch[constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS] = payloads;
            }
            if (Object.keys(statePatch).length) {
                this._set(statePatch);
            }
            if (flags === false && payloads === false) {
                this._remove([constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS, constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS]);
            }
            else if (flags === false) {
                this._remove(constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS);
            }
            else if (payloads === false) {
                this._remove(constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS);
            }
            this._fireFeatureFlagsCallbacks();
            if (flags === false) {
                forceDebugLogger.info('Flag overrides cleared');
            }
            else if (flags) {
                forceDebugLogger.info('Flag overrides set', { flags: flags });
            }
            if (payloads === false) {
                forceDebugLogger.info('Payload overrides cleared');
            }
            else if (payloads) {
                forceDebugLogger.info('Payload overrides set', { payloads: payloads });
            }
            return;
        }
        // Fallback: treat as Record<string, string | boolean>, e.g. {'beta-feature': 'variant'}
        if (overrideOptions && typeof overrideOptions === 'object') {
            this._set((_b = {},
                _b[constants_1.PERSISTENCE_OVERRIDE_FEATURE_FLAGS] = overrideOptions,
                _b));
            this._fireFeatureFlagsCallbacks();
            forceDebugLogger.info('Flag overrides set', { flags: overrideOptions });
            return;
        }
        this._logger.warn('Invalid overrideOptions provided to overrideFeatureFlags', { overrideOptions: overrideOptions });
    };
    /*
     * Register an event listener that runs when feature flags become available or when they change.
     * If there are flags, the listener is called immediately in addition to being called on future changes.
     *
     * ### Usage:
     *
     *     posthog.onFeatureFlags(function(featureFlags, featureFlagsVariants, { errorsLoading }) { // do something })
     *
     * @param {Function} [callback] The callback function will be called once the feature flags are ready or when they are updated.
     *                              It'll return a list of feature flags enabled for the user, the variants,
     *                              and also a context object indicating whether we succeeded to fetch the flags or not.
     * @returns {Function} A function that can be called to unsubscribe the listener. Used by useEffect when the component unmounts.
     */
    PostHogFeatureFlags.prototype.onFeatureFlags = function (callback) {
        var _this = this;
        this.addFeatureFlagsHandler(callback);
        if (this._hasLoadedFlags) {
            var _a = this._prepareFeatureFlagsForCallbacks(), flags = _a.flags, flagVariants = _a.flagVariants;
            // Isolate the callback so a user-provided handler that throws surfaces as a logged
            // error rather than propagating out of onFeatureFlags as a posthog-js SDK error.
            try {
                callback(flags, flagVariants);
            }
            catch (error) {
                this._logger.error('Error while running feature flags callback', error);
            }
        }
        return function () { return _this.removeFeatureFlagsHandler(callback); };
    };
    PostHogFeatureFlags.prototype.updateEarlyAccessFeatureEnrollment = function (key, isEnrolled, stage) {
        var _a, _b, _c, _d;
        var _this = this;
        var _e, _f, _g;
        var existing_early_access_features = this._prop(constants_1.PERSISTENCE_EARLY_ACCESS_FEATURES) || [];
        var feature = existing_early_access_features.find(function (f) { return f.flagKey === key; });
        var enrollmentPersonProp = (_a = {},
            _a["$feature_enrollment/".concat(key)] = isEnrolled,
            _a);
        var properties = {
            $feature_flag: key,
            $feature_enrollment: isEnrolled,
            $set: enrollmentPersonProp,
        };
        if (feature) {
            properties['$early_access_feature_name'] = feature.name;
        }
        if (stage) {
            properties['$feature_enrollment_stage'] = stage;
        }
        var newFlags = __assign(__assign({}, this.getFlagVariants()), (_b = {}, _b[key] = isEnrolled, _b));
        (_f = (_e = this._instance) === null || _e === void 0 ? void 0 : _e.persistence) === null || _f === void 0 ? void 0 : _f.markCrossTabFeatureFlagChanges((_c = {},
            _c[constants_1.PERSISTENCE_ACTIVE_FEATURE_FLAGS] = [key],
            _c[constants_1.ENABLED_FEATURE_FLAGS] = [key],
            _c[constants_1.STORED_PERSON_PROPERTIES_KEY] = Object.keys(enrollmentPersonProp),
            _c));
        this._set((_d = {},
            _d[constants_1.PERSISTENCE_ACTIVE_FEATURE_FLAGS] = Object.keys((0, exports.filterActiveFeatureFlags)(newFlags)),
            _d[constants_1.ENABLED_FEATURE_FLAGS] = newFlags,
            _d[constants_1.STORED_PERSON_PROPERTIES_KEY] = __assign(__assign({}, (this._prop(constants_1.STORED_PERSON_PROPERTIES_KEY) || {})), enrollmentPersonProp),
            _d));
        this._fireFeatureFlagsCallbacks();
        try {
            void ((_g = this._client) === null || _g === void 0 ? void 0 : _g.capture('$feature_enrollment_update', properties).catch(function (error) {
                _this._logger.error('Failed to capture early access feature enrollment', error);
            }));
        }
        catch (error) {
            this._logger.error('Failed to capture early access feature enrollment', error);
        }
    };
    PostHogFeatureFlags.prototype.getEarlyAccessFeatures = function (callback, force_reload, stages) {
        if (force_reload === void 0) { force_reload = false; }
        var existing_early_access_features = this._prop(constants_1.PERSISTENCE_EARLY_ACCESS_FEATURES);
        if (existing_early_access_features && !force_reload) {
            callback(existing_early_access_features);
            return;
        }
        void this._getEarlyAccessFeatures(callback, stages);
    };
    // TODO: Consider moving early access features to their own extension.
    PostHogFeatureFlags.prototype._getEarlyAccessFeatures = function (callback, stages) {
        return __awaiter(this, void 0, void 0, function () {
            var client, stageParams, earlyAccessFeatures, response, error_2;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        client = this._client;
                        if (!client) {
                            return [2 /*return*/];
                        }
                        stageParams = stages ? "&".concat(stages.map(function (s) { return "stage=".concat(s); }).join('&')) : '';
                        _b.label = 1;
                    case 1:
                        _b.trys.push([1, 3, , 4]);
                        return [4 /*yield*/, client.sendRequest("/api/early_access_features/?token=".concat(client.projectToken).concat(stageParams), {
                                target: 'api',
                                method: 'GET',
                                sentAt: 'query',
                            })];
                    case 2:
                        response = _b.sent();
                        if (!response.json) {
                            return [2 /*return*/];
                        }
                        earlyAccessFeatures = response.json.earlyAccessFeatures;
                        this._set((_a = {}, _a[constants_1.PERSISTENCE_EARLY_ACCESS_FEATURES] = earlyAccessFeatures, _a));
                        return [3 /*break*/, 4];
                    case 3:
                        error_2 = _b.sent();
                        this._logger.error('Early access feature request failed', error_2);
                        return [2 /*return*/];
                    case 4:
                        try {
                            callback(earlyAccessFeatures);
                        }
                        catch (error) {
                            this._logger.error('Early access feature callback failed', error);
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    PostHogFeatureFlags.prototype._prepareFeatureFlagsForCallbacks = function () {
        var flags = this.getFlags();
        var flagVariants = this.getFlagVariants();
        // Return truthy
        var truthyFlags = flags.filter(function (flag) { return flagVariants[flag]; });
        var truthyFlagVariants = Object.keys(flagVariants)
            .filter(function (variantKey) { return flagVariants[variantKey]; })
            .reduce(function (res, key) {
            res[key] = flagVariants[key];
            return res;
        }, {});
        return {
            flags: truthyFlags,
            flagVariants: truthyFlagVariants,
        };
    };
    PostHogFeatureFlags.prototype._fireFeatureFlagsCallbacks = function (errorsLoading) {
        var _this = this;
        this._rebuildEventProperties();
        var _a = this._prepareFeatureFlagsForCallbacks(), flags = _a.flags, flagVariants = _a.flagVariants;
        this.featureFlagEventHandlers.forEach(function (handler) {
            // Isolate each handler: a user-provided onFeatureFlags callback that throws must not
            // break the callback chain (preventing later handlers from firing) or surface as a
            // posthog-js SDK error in error tracking.
            try {
                handler(flags, flagVariants, { errorsLoading: errorsLoading });
            }
            catch (error) {
                _this._logger.error('Error while running feature flags callback', error);
            }
        });
    };
    /**
     * Set override person properties for feature flags.
     * This is used when dealing with new persons / where you don't want to wait for ingestion
     * to update user properties.
     */
    PostHogFeatureFlags.prototype.setPersonPropertiesForFlags = function (properties, reloadFeatureFlags) {
        if (reloadFeatureFlags === void 0) { reloadFeatureFlags = true; }
        this._setPersonPropertiesForFlags(properties, reloadFeatureFlags);
    };
    PostHogFeatureFlags.prototype._setPersonPropertiesForFlags = function (properties, reloadFeatureFlags) {
        var _a;
        if (reloadFeatureFlags === void 0) { reloadFeatureFlags = true; }
        var existingProperties = this._prop(constants_1.STORED_PERSON_PROPERTIES_KEY) || {};
        // If the caller passes { $set, $set_once }, split them apart so we can apply $set_once
        // semantics (skip keys that already exist). Otherwise treat all properties as $set for
        // backward compatibility with the public API.
        var propsToSet = (properties === null || properties === void 0 ? void 0 : properties['$set']) || (!(properties === null || properties === void 0 ? void 0 : properties['$set_once']) ? properties : {});
        var propsToSetOnce = properties === null || properties === void 0 ? void 0 : properties['$set_once'];
        var setOnceProps = {};
        if (propsToSetOnce) {
            for (var key in propsToSetOnce) {
                if (Object.prototype.hasOwnProperty.call(propsToSetOnce, key)) {
                    if (!(key in existingProperties)) {
                        setOnceProps[key] = propsToSetOnce[key];
                    }
                }
            }
        }
        this._set((_a = {},
            _a[constants_1.STORED_PERSON_PROPERTIES_KEY] = __assign(__assign(__assign({}, existingProperties), setOnceProps), propsToSet),
            _a));
        if (reloadFeatureFlags) {
            this.reloadFeatureFlags();
        }
    };
    /**
     * Remove override person properties used for feature flags.
     * This is the counterpart to setPersonPropertiesForFlags, used when person properties
     * are unset so flags re-evaluate without the removed values.
     */
    PostHogFeatureFlags.prototype.unsetPersonPropertiesForFlags = function (propertyNames, reloadFeatureFlags) {
        var _a;
        if (reloadFeatureFlags === void 0) { reloadFeatureFlags = true; }
        var existingProperties = this._prop(constants_1.STORED_PERSON_PROPERTIES_KEY) || {};
        var nextProperties = __assign({}, existingProperties);
        propertyNames.forEach(function (name) {
            delete nextProperties[name];
        });
        this._set((_a = {}, _a[constants_1.STORED_PERSON_PROPERTIES_KEY] = nextProperties, _a));
        if (reloadFeatureFlags) {
            this.reloadFeatureFlags();
        }
    };
    PostHogFeatureFlags.prototype.resetPersonPropertiesForFlags = function (reloadFeatureFlags) {
        if (reloadFeatureFlags === void 0) { reloadFeatureFlags = true; }
        this._remove(constants_1.STORED_PERSON_PROPERTIES_KEY);
        if (reloadFeatureFlags) {
            this.reloadFeatureFlags();
        }
    };
    /**
     * Set override group properties for feature flags.
     * This is used when dealing with new groups / where you don't want to wait for ingestion
     * to update properties.
     * Takes in an object, the key of which is the group type.
     * For example:
     *     setGroupPropertiesForFlags({'organization': { name: 'CYZ', employees: '11' } })
     */
    PostHogFeatureFlags.prototype.setGroupPropertiesForFlags = function (properties, reloadFeatureFlags) {
        var e_7, _a, _b;
        if (reloadFeatureFlags === void 0) { reloadFeatureFlags = true; }
        var existingProperties = (this._prop(constants_1.STORED_GROUP_PROPERTIES_KEY) || {});
        var nextProperties = __assign({}, existingProperties);
        try {
            for (var _c = __values(Object.keys(properties)), _d = _c.next(); !_d.done; _d = _c.next()) {
                var groupType = _d.value;
                nextProperties[groupType] = __assign(__assign({}, existingProperties[groupType]), properties[groupType]);
            }
        }
        catch (e_7_1) { e_7 = { error: e_7_1 }; }
        finally {
            try {
                if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
            }
            finally { if (e_7) throw e_7.error; }
        }
        this._set((_b = {}, _b[constants_1.STORED_GROUP_PROPERTIES_KEY] = nextProperties, _b));
        if (reloadFeatureFlags) {
            this.reloadFeatureFlags();
        }
    };
    PostHogFeatureFlags.prototype.resetGroupPropertiesForFlags = function (group_type) {
        var _a, _b;
        if (group_type) {
            var existingProperties = this._prop(constants_1.STORED_GROUP_PROPERTIES_KEY) || {};
            this._set((_a = {},
                _a[constants_1.STORED_GROUP_PROPERTIES_KEY] = __assign(__assign({}, existingProperties), (_b = {}, _b[group_type] = {}, _b)),
                _a));
        }
        else {
            this._remove(constants_1.STORED_GROUP_PROPERTIES_KEY);
        }
    };
    PostHogFeatureFlags.prototype.reset = function () {
        this._requestGeneration++;
        this._additionalReloadRequested = false;
        this._baseEventProperties = {};
        this._eventPropertiesWithFlagValues = {};
        this._hasLoadedFlags = false;
        this._reloadingDisabled = false;
        this._flagsLoadedFromRemote = false;
        this.$anon_distinct_id = undefined;
        this._clearDebouncer();
        this._override_warning = false;
        this._consecutiveStatusZeroFailures = 0;
    };
    return PostHogFeatureFlags;
}());
exports.PostHogFeatureFlags = PostHogFeatureFlags;
//# sourceMappingURL=posthog-featureflags.js.map