Skip to main content
Glama
storage.js12.5 kB
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 { extend } from './utils'; import { DISTINCT_ID, ENABLE_PERSON_PROCESSING, INITIAL_PERSON_INFO, SESSION_ID, SESSION_RECORDING_IS_SAMPLED, } from './constants'; import { isNull, isUndefined } from './utils/type-utils'; import { logger } from './utils/logger'; import { window, document } from './utils/globals'; import { uuidv7 } from './uuidv7'; var Y1970 = 'Thu, 01 Jan 1970 00:00:00 GMT'; // we store the discovered subdomain in memory because it might be read multiple times var firstNonPublicSubDomain = ''; // helper to allow tests to clear this "cache" export var resetSubDomainCache = function () { firstNonPublicSubDomain = ''; }; /** * Browsers don't offer a way to check if something is a public suffix * e.g. `.com.au`, `.io`, `.org.uk` * * But they do reject cookies set on public suffixes * Setting a cookie on `.co.uk` would mean it was sent for every `.co.uk` site visited * * So, we can use this to check if a domain is a public suffix * by trying to set a cookie on a subdomain of the provided hostname * until the browser accepts it * * inspired by https://github.com/AngusFu/browser-root-domain */ export function seekFirstNonPublicSubDomain(hostname, cookieJar) { if (cookieJar === void 0) { cookieJar = document; } if (firstNonPublicSubDomain) { return firstNonPublicSubDomain; } if (!cookieJar) { return ''; } if (['localhost', '127.0.0.1'].includes(hostname)) return ''; var list = hostname.split('.'); var len = Math.min(list.length, 8); // paranoia - we know this number should be small var key = 'dmn_chk_' + uuidv7(); var R = new RegExp('(^|;)\\s*' + key + '=1'); while (!firstNonPublicSubDomain && len--) { var candidate = list.slice(len).join('.'); var candidateCookieValue = key + '=1;domain=.' + candidate; // try to set cookie cookieJar.cookie = candidateCookieValue; if (R.test(cookieJar.cookie)) { // the cookie was accepted by the browser, remove the test cookie cookieJar.cookie = candidateCookieValue + ';expires=' + Y1970; firstNonPublicSubDomain = candidate; } } return firstNonPublicSubDomain; } var DOMAIN_MATCH_REGEX = /[a-z0-9][a-z0-9-]+\.[a-z]{2,}$/i; var originalCookieDomainFn = function (hostname) { var matches = hostname.match(DOMAIN_MATCH_REGEX); return matches ? matches[0] : ''; }; export function chooseCookieDomain(hostname, cross_subdomain) { if (cross_subdomain) { // NOTE: Could we use this for cross domain tracking? var matchedSubDomain = seekFirstNonPublicSubDomain(hostname); if (!matchedSubDomain) { var originalMatch = originalCookieDomainFn(hostname); if (originalMatch !== matchedSubDomain) { logger.info('Warning: cookie subdomain discovery mismatch', originalMatch, matchedSubDomain); } matchedSubDomain = originalMatch; } return matchedSubDomain ? '; domain=.' + matchedSubDomain : ''; } return ''; } // Methods partially borrowed from quirksmode.org/js/cookies.html export var cookieStore = { is_supported: function () { return !!document; }, error: function (msg) { logger.error('cookieStore error: ' + msg); }, get: function (name) { if (!document) { return; } try { var nameEQ = name + '='; var ca = document.cookie.split(';').filter(function (x) { return x.length; }); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1, c.length); } if (c.indexOf(nameEQ) === 0) { return decodeURIComponent(c.substring(nameEQ.length, c.length)); } } } catch (_a) { } return null; }, parse: function (name) { var cookie; try { cookie = JSON.parse(cookieStore.get(name)) || {}; } catch (_a) { // noop } return cookie; }, set: function (name, value, days, cross_subdomain, is_secure) { if (!document) { return; } try { var expires = '', secure = ''; var cdomain = chooseCookieDomain(document.location.hostname, cross_subdomain); if (days) { var date = new Date(); date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); expires = '; expires=' + date.toUTCString(); } if (is_secure) { secure = '; secure'; } var new_cookie_val = name + '=' + encodeURIComponent(JSON.stringify(value)) + expires + '; SameSite=Lax; path=/' + cdomain + secure; // 4096 bytes is the size at which some browsers (e.g. firefox) will not store a cookie, warn slightly before that if (new_cookie_val.length > 4096 * 0.9) { logger.warn('cookieStore warning: large cookie, len=' + new_cookie_val.length); } document.cookie = new_cookie_val; return new_cookie_val; } catch (_a) { return; } }, remove: function (name, cross_subdomain) { try { cookieStore.set(name, '', -1, cross_subdomain); } catch (_a) { return; } }, }; var _localStorage_supported = null; export var localStore = { is_supported: function () { if (!isNull(_localStorage_supported)) { return _localStorage_supported; } var supported = true; if (!isUndefined(window)) { try { var key = '__mplssupport__', val = 'xyz'; localStore.set(key, val); if (localStore.get(key) !== '"xyz"') { supported = false; } localStore.remove(key); } catch (_a) { supported = false; } } else { supported = false; } if (!supported) { logger.error('localStorage unsupported; falling back to cookie store'); } _localStorage_supported = supported; return supported; }, error: function (msg) { logger.error('localStorage error: ' + msg); }, get: function (name) { try { return window === null || window === void 0 ? void 0 : window.localStorage.getItem(name); } catch (err) { localStore.error(err); } return null; }, parse: function (name) { try { return JSON.parse(localStore.get(name)) || {}; } catch (_a) { // noop } return null; }, set: function (name, value) { try { window === null || window === void 0 ? void 0 : window.localStorage.setItem(name, JSON.stringify(value)); } catch (err) { localStore.error(err); } }, remove: function (name) { try { window === null || window === void 0 ? void 0 : window.localStorage.removeItem(name); } catch (err) { localStore.error(err); } }, }; // Use localstorage for most data but still use cookie for COOKIE_PERSISTED_PROPERTIES // This solves issues with cookies having too much data in them causing headers too large // Also makes sure we don't have to send a ton of data to the server var COOKIE_PERSISTED_PROPERTIES = [ DISTINCT_ID, SESSION_ID, SESSION_RECORDING_IS_SAMPLED, ENABLE_PERSON_PROCESSING, INITIAL_PERSON_INFO, ]; export var localPlusCookieStore = __assign(__assign({}, localStore), { parse: function (name) { try { var cookieProperties = {}; try { // See if there's a cookie stored with data. cookieProperties = cookieStore.parse(name) || {}; } catch (_a) { } var value = extend(cookieProperties, JSON.parse(localStore.get(name) || '{}')); localStore.set(name, value); return value; } catch (_b) { // noop } return null; }, set: function (name, value, days, cross_subdomain, is_secure, debug) { try { localStore.set(name, value, undefined, undefined, debug); var cookiePersistedProperties_1 = {}; COOKIE_PERSISTED_PROPERTIES.forEach(function (key) { if (value[key]) { cookiePersistedProperties_1[key] = value[key]; } }); if (Object.keys(cookiePersistedProperties_1).length) { cookieStore.set(name, cookiePersistedProperties_1, days, cross_subdomain, is_secure, debug); } } catch (err) { localStore.error(err); } }, remove: function (name, cross_subdomain) { try { window === null || window === void 0 ? void 0 : window.localStorage.removeItem(name); cookieStore.remove(name, cross_subdomain); } catch (err) { localStore.error(err); } } }); var memoryStorage = {}; // Storage that only lasts the length of the pageview if we don't want to use cookies export var memoryStore = { is_supported: function () { return true; }, error: function (msg) { logger.error('memoryStorage error: ' + msg); }, get: function (name) { return memoryStorage[name] || null; }, parse: function (name) { return memoryStorage[name] || null; }, set: function (name, value) { memoryStorage[name] = value; }, remove: function (name) { delete memoryStorage[name]; }, }; var sessionStorageSupported = null; export var resetSessionStorageSupported = function () { sessionStorageSupported = null; }; // Storage that only lasts the length of a tab/window. Survives page refreshes export var sessionStore = { is_supported: function () { if (!isNull(sessionStorageSupported)) { return sessionStorageSupported; } sessionStorageSupported = true; if (!isUndefined(window)) { try { var key = '__support__', val = 'xyz'; sessionStore.set(key, val); if (sessionStore.get(key) !== '"xyz"') { sessionStorageSupported = false; } sessionStore.remove(key); } catch (_a) { sessionStorageSupported = false; } } else { sessionStorageSupported = false; } return sessionStorageSupported; }, error: function (msg) { logger.error('sessionStorage error: ', msg); }, get: function (name) { try { return window === null || window === void 0 ? void 0 : window.sessionStorage.getItem(name); } catch (err) { sessionStore.error(err); } return null; }, parse: function (name) { try { return JSON.parse(sessionStore.get(name)) || null; } catch (_a) { // noop } return null; }, set: function (name, value) { try { window === null || window === void 0 ? void 0 : window.sessionStorage.setItem(name, JSON.stringify(value)); } catch (err) { sessionStore.error(err); } }, remove: function (name) { try { window === null || window === void 0 ? void 0 : window.sessionStorage.removeItem(name); } catch (err) { sessionStore.error(err); } }, }; //# sourceMappingURL=storage.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