Skip to main content
Glama
posthog-persistence.js12.5 kB
/* eslint camelcase: "off" */ 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); }; import { each, extend, include, stripEmptyProperties } from './utils'; import { cookieStore, localPlusCookieStore, localStore, memoryStore, sessionStore } from './storage'; import { ENABLED_FEATURE_FLAGS, EVENT_TIMERS_KEY, INITIAL_CAMPAIGN_PARAMS, INITIAL_PERSON_INFO, INITIAL_REFERRER_INFO, PERSISTENCE_RESERVED_PROPERTIES, } from './constants'; import { isEmptyObject, isObject, isUndefined } from './utils/type-utils'; import { Info } from './utils/event-utils'; import { logger } from './utils/logger'; import { stripLeadingDollar } from './utils/string-utils'; var CASE_INSENSITIVE_PERSISTENCE_TYPES = [ 'cookie', 'localstorage', 'localstorage+cookie', 'sessionstorage', 'memory', ]; var parseName = function (config) { var token = ''; if (config['token']) { token = config['token'].replace(/\+/g, 'PL').replace(/\//g, 'SL').replace(/=/g, 'EQ'); } if (config['persistence_name']) { return 'ph_' + config['persistence_name']; } else { return 'ph_' + token + '_posthog'; } }; /** * PostHog Persistence Object * @constructor */ var PostHogPersistence = /** @class */ (function () { function PostHogPersistence(config) { this.config = config; this.props = {}; this.campaign_params_saved = false; this.name = parseName(config); this.storage = this.buildStorage(config); this.load(); if (config.debug) { logger.info('Persistence loaded', config['persistence'], __assign({}, this.props)); } this.update_config(config, config); this.save(); } PostHogPersistence.prototype.buildStorage = function (config) { if (CASE_INSENSITIVE_PERSISTENCE_TYPES.indexOf(config['persistence'].toLowerCase()) === -1) { logger.critical('Unknown persistence type ' + config['persistence'] + '; falling back to localStorage+cookie'); config['persistence'] = 'localStorage+cookie'; } var store; // We handle storage type in a case-insensitive way for backwards compatibility var storage_type = config['persistence'].toLowerCase(); if (storage_type === 'localstorage' && localStore.is_supported()) { store = localStore; } else if (storage_type === 'localstorage+cookie' && localPlusCookieStore.is_supported()) { store = localPlusCookieStore; } else if (storage_type === 'sessionstorage' && sessionStore.is_supported()) { store = sessionStore; } else if (storage_type === 'memory') { store = memoryStore; } else if (storage_type === 'cookie') { store = cookieStore; } else if (localPlusCookieStore.is_supported()) { // selected storage type wasn't supported, fallback to 'localstorage+cookie' if possible store = localPlusCookieStore; } else { store = cookieStore; } return store; }; PostHogPersistence.prototype.properties = function () { var p = {}; // Filter out reserved properties each(this.props, function (v, k) { if (k === ENABLED_FEATURE_FLAGS && isObject(v)) { var keys = Object.keys(v); for (var i = 0; i < keys.length; i++) { p["$feature/".concat(keys[i])] = v[keys[i]]; } } else if (!include(PERSISTENCE_RESERVED_PROPERTIES, k)) { p[k] = v; } }); return p; }; PostHogPersistence.prototype.load = function () { if (this.disabled) { return; } var entry = this.storage.parse(this.name); if (entry) { this.props = extend({}, entry); } }; /** * NOTE: Saving frequently causes issues with Recordings and Consent Management Platform (CMP) tools which * observe cookie changes, and modify their UI, often causing infinite loops. * As such callers of this should ideally check that the data has changed beforehand */ PostHogPersistence.prototype.save = function () { if (this.disabled) { return; } this.storage.set(this.name, this.props, this.expire_days, this.cross_subdomain, this.secure, this.config.debug); }; PostHogPersistence.prototype.remove = function () { // remove both domain and subdomain cookies this.storage.remove(this.name, false); this.storage.remove(this.name, true); }; // removes the storage entry and deletes all loaded data // forced name for tests PostHogPersistence.prototype.clear = function () { this.remove(); this.props = {}; }; /** * @param {Object} props * @param {*=} default_value * @param {number=} days */ PostHogPersistence.prototype.register_once = function (props, default_value, days) { var _this = this; if (isObject(props)) { if (isUndefined(default_value)) { default_value = 'None'; } this.expire_days = isUndefined(days) ? this.default_expiry : days; var hasChanges_1 = false; each(props, function (val, prop) { if (!_this.props.hasOwnProperty(prop) || _this.props[prop] === default_value) { _this.props[prop] = val; hasChanges_1 = true; } }); if (hasChanges_1) { this.save(); return true; } } return false; }; /** * @param {Object} props * @param {number=} days */ PostHogPersistence.prototype.register = function (props, days) { var _this = this; if (isObject(props)) { this.expire_days = isUndefined(days) ? this.default_expiry : days; var hasChanges_2 = false; each(props, function (val, prop) { if (props.hasOwnProperty(prop) && _this.props[prop] !== val) { _this.props[prop] = val; hasChanges_2 = true; } }); if (hasChanges_2) { this.save(); return true; } } return false; }; PostHogPersistence.prototype.unregister = function (prop) { if (prop in this.props) { delete this.props[prop]; this.save(); } }; PostHogPersistence.prototype.update_campaign_params = function () { if (!this.campaign_params_saved) { var campaignParams = Info.campaignParams({ customTrackedParams: this.config.custom_campaign_params, maskPersonalDataProperties: this.config.mask_personal_data_properties, customPersonalDataProperties: this.config.custom_personal_data_properties, }); // only save campaign params if there were any if (!isEmptyObject(stripEmptyProperties(campaignParams))) { this.register(campaignParams); } this.campaign_params_saved = true; } }; PostHogPersistence.prototype.update_search_keyword = function () { this.register(Info.searchInfo()); }; PostHogPersistence.prototype.update_referrer_info = function () { this.register_once(Info.referrerInfo(), undefined); }; PostHogPersistence.prototype.set_initial_person_info = function () { var _a; if (this.props[INITIAL_CAMPAIGN_PARAMS] || this.props[INITIAL_REFERRER_INFO]) { // the user has initial properties stored the previous way, don't save them again return; } this.register_once((_a = {}, _a[INITIAL_PERSON_INFO] = Info.personInfo({ maskPersonalDataProperties: this.config.mask_personal_data_properties, customPersonalDataProperties: this.config.custom_personal_data_properties, }), _a), undefined); }; PostHogPersistence.prototype.get_referrer_info = function () { return stripEmptyProperties({ $referrer: this['props']['$referrer'], $referring_domain: this['props']['$referring_domain'], }); }; PostHogPersistence.prototype.get_initial_props = function () { var _this = this; var p = {}; // this section isn't written to anymore, but we should keep reading from it for backwards compatibility // for a while each([INITIAL_REFERRER_INFO, INITIAL_CAMPAIGN_PARAMS], function (key) { var initialReferrerInfo = _this.props[key]; if (initialReferrerInfo) { each(initialReferrerInfo, function (v, k) { p['$initial_' + stripLeadingDollar(k)] = v; }); } }); var initialPersonInfo = this.props[INITIAL_PERSON_INFO]; if (initialPersonInfo) { var initialPersonProps = Info.initialPersonPropsFromInfo(initialPersonInfo); extend(p, initialPersonProps); } return p; }; // safely fills the passed in object with stored properties, // does not override any properties defined in both // returns the passed in object PostHogPersistence.prototype.safe_merge = function (props) { each(this.props, function (val, prop) { if (!(prop in props)) { props[prop] = val; } }); return props; }; PostHogPersistence.prototype.update_config = function (config, oldConfig) { this.default_expiry = this.expire_days = config['cookie_expiration']; this.set_disabled(config['disable_persistence']); this.set_cross_subdomain(config['cross_subdomain_cookie']); this.set_secure(config['secure_cookie']); if (config.persistence !== oldConfig.persistence) { // If the persistence type has changed, we need to migrate the data. var newStore = this.buildStorage(config); var props = this.props; // clear the old store this.clear(); this.storage = newStore; this.props = props; this.save(); } }; PostHogPersistence.prototype.set_disabled = function (disabled) { this.disabled = disabled; if (this.disabled) { this.remove(); } else { this.save(); } }; PostHogPersistence.prototype.set_cross_subdomain = function (cross_subdomain) { if (cross_subdomain !== this.cross_subdomain) { this.cross_subdomain = cross_subdomain; this.remove(); this.save(); } }; PostHogPersistence.prototype.get_cross_subdomain = function () { return !!this.cross_subdomain; }; PostHogPersistence.prototype.set_secure = function (secure) { if (secure !== this.secure) { this.secure = secure; this.remove(); this.save(); } }; PostHogPersistence.prototype.set_event_timer = function (event_name, timestamp) { var timers = this.props[EVENT_TIMERS_KEY] || {}; timers[event_name] = timestamp; this.props[EVENT_TIMERS_KEY] = timers; this.save(); }; PostHogPersistence.prototype.remove_event_timer = function (event_name) { var timers = this.props[EVENT_TIMERS_KEY] || {}; var timestamp = timers[event_name]; if (!isUndefined(timestamp)) { delete this.props[EVENT_TIMERS_KEY][event_name]; this.save(); } return timestamp; }; PostHogPersistence.prototype.get_property = function (prop) { return this.props[prop]; }; PostHogPersistence.prototype.set_property = function (prop, to) { this.props[prop] = to; this.save(); }; return PostHogPersistence; }()); export { PostHogPersistence }; //# sourceMappingURL=posthog-persistence.js.map

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sadiuysal/mem0-mcp-server-ts'

If you have feedback or need assistance with the MCP directory API, please join our Discord server