@altertable/altertable-js 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
- /*! @altertable/altertable-js 0.5.2 | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
- var Altertable=(()=>{var I=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var _e=Object.prototype.hasOwnProperty;var he=(n,e)=>{for(var t in e)I(n,t,{get:e[t],enumerable:!0})},fe=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of pe(e))!_e.call(n,r)&&r!==t&&I(n,r,{get:()=>e[r],enumerable:!(s=de(e,r))||s.enumerable});return n};var Ee=n=>fe(I({},"__esModule",{value:!0}),n);var Ae={};he(Ae,{TrackingConsent:()=>i,altertable:()=>w});function x(n,e){return(...t)=>[n,...t].join(e)}var P="https://api.altertable.ai",S="production",U="localStorage+cookie",me="atbl",T=x(me,"."),c=T("check"),N="session",L="visitor",ve=1e3*60,$=100,V=30*ve,O=1e3,M="$pageview",B="$lib",z="$lib_version",F="$referer",K="$release",q="$url",G="$viewport",i={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},y=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],k=new Set(["[object Object]","0","NaN","none","None","null"]);var h=class{_queue=[];_queueMaxSize;constructor(e){this._queueMaxSize=e}enqueue(e,t,s){this._queue.length>=this._queueMaxSize&&this._queue.shift(),this._queue.push({eventType:e,payload:t,context:s,sentAt:new Date})}flush(){let e=[...this._queue];return this._queue=[],e}clear(){this._queue=[]}getSize(){return this._queue.length}};function o(n,e=()=>{}){return typeof window>"u"?e():n({window})}function Y(){return o(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function a(n,e){if(!n)throw new Error("Invariant failed")}function Q(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v0.5.2 %c\u2022 Debug mode enabled";f.current[e]||(f.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[s,r]=Se(e.event),[g,l]=Te(e.environment),[W,H]=ke(e.timestamp),[J,Z]=be(t);console.groupCollapsed(`[${n}] %c${s}%c [${g}] %c(${W}) %c${J}`,r,l,H,Z);let[ee,te]=b("User ID"),[ne,se]=C(e.user_id??"Not set"),[re,ie]=b("Visitor ID"),[oe,ae]=C(e.visitor_id??"Not set"),[ge,le]=b("Session ID"),[ce,ue]=C(e.session_id??"Not set");console.log(`%c${ee} %c${ne}`,te,se),console.log(`%c${re} %c${oe}`,ie,ae),console.log(`%c${ge} %c${ce}`,le,ue),console.table(e.properties),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!r){f.current[s]=!0;let g=`[${n}] ${s}`;console.warn(g,...t);try{throw new Error(g)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var f={current:{}};function Ie(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function Se(n){return[n,"background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;"]}function Te(n){return[n,`color: ${ye(n)}; font-weight: 400;`]}function ye(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function ke(n){return[Ie(n),"color: #64748b; font-weight: 400;"]}function b(n){return[n,"color: #64748b; font-size: 11px;"]}function C(n){return[n,'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: "SF Mono", "Monaco", monospace; font-size: 11px;']}function be(n){switch(n){case i.GRANTED:return["",""];case i.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case i.PENDING:case i.DISMISSED:return["PENDING","background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];default:return["UNKNOWN","background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"]}}function R(n){if(typeof globalThis.crypto<"u"&&typeof globalThis.crypto.randomUUID=="function")try{return`${n}-${crypto.randomUUID()}`}catch{}return`${n}-${Math.random().toString(36).substring(2)}`}var E=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??i.PENDING,this._sessionData=this._createDefaultSessionData()}init(){let e=this._storage.getItem(this._storageKey);if(!e){this._sessionData=this._createDefaultSessionData(),this._persistToStorage();return}try{let t=JSON.parse(e);this._sessionData={visitorId:t.visitorId||this._generateVisitorId(),sessionId:t.sessionId||this._generateSessionId(),userId:t.userId||null,lastEventAt:t.lastEventAt||null,trackingConsent:Ce(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getVisitorId(){return this._sessionData.visitorId}getSessionId(){return this._sessionData.sessionId}getUserId(){return this._sessionData.userId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}setUserId(e){this._sessionData.userId=e,this._persistToStorage()}setTrackingConsent(e){this._sessionData.trackingConsent=e,this._persistToStorage()}updateLastEventAt(e){this._sessionData.lastEventAt=e,this._persistToStorage()}renewSessionIfNeeded(){return this._shouldRenewSession()?(this._renewSession(),this._persistToStorage(),!0):!1}reset({resetVisitorId:e=!1,resetSessionId:t=!0,resetTrackingConsent:s=!1}={}){e&&(this._sessionData.visitorId=this._generateVisitorId()),t&&(this._sessionData.sessionId=this._generateSessionId()),s&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.userId=null,this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{visitorId:this._generateVisitorId(),sessionId:this._generateSessionId(),userId:null,lastEventAt:null,trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return R(N)}_generateVisitorId(){return R(L)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),s=new Date(e).getTime();return t-s>V}_renewSession(){this._sessionData.sessionId=this._generateSessionId(),this._sessionData.lastEventAt=null}_persistToStorage(){try{this._storage.setItem(this._storageKey,JSON.stringify(this._sessionData))}catch{this._logger.warnDev("Failed to persist session data to storage.")}}};function Ce(n){return typeof n=="string"&&Object.values(i).includes(n)}function D(n,e,t){for(let s of t){let r=e.getItem(s);r!==null&&(n.setItem(s,r),e.removeItem(s))}}var u=class{store={};getItem(e){return this.store[e]??null}setItem(e,t){this.store[e]=t}removeItem(e){delete this.store[e]}migrate(e,t){D(this,e,t)}},_=class{getItem(e){return o(({window:t})=>{let s=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return s?decodeURIComponent(s[2]):null},()=>null)}setItem(e,t){o(({window:s})=>{s.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){o(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){D(this,e,t)}},d=class{constructor(e){this.storage=e}getItem(e){return o(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){o(({window:s})=>{try{s[this.storage].setItem(e,t)}catch{}})}removeItem(e){o(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){D(this,e,t)}},A=class{localStore=new d("localStorage");cookieStore=new _;getItem(e){return this.localStore.getItem(e)??this.cookieStore.getItem(e)}setItem(e,t){this.localStore.setItem(e,t),this.cookieStore.setItem(e,t)}removeItem(e){this.localStore.removeItem(e),this.cookieStore.removeItem(e)}migrate(e,t){for(let s of t){let r=e.getItem(s);r!==null&&(this.localStore.setItem(s,r),this.cookieStore.setItem(s,r))}for(let s of t)e.removeItem(s)}};function p(n){return o(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${c}=1`;let t=e.document.cookie.indexOf(`${c}=`)!==-1;return e.document.cookie=`${c}=; Max-Age=0`,t}else return e[n].setItem(c,"1"),e[n].removeItem(c),!0}catch{return!1}},()=>!1)}function m(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return p("localStorage")?new d("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),m("localStorage+cookie",e));case"localStorage+cookie":{let s=p("localStorage"),r=p("cookie");return s&&r?new A:r?(t("localStorage+cookie not fully supported, falling back to cookie."),new _):s?(t("cookie not supported, falling back to localStorage."),new d("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new u)}case"sessionStorage":return p("sessionStorage")?new d("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new u);case"cookie":return p("cookie")?new _:(t("cookie not supported, falling back to memory."),new u);case"memory":return new u;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Re=[...y,...k].map(n=>`- "${n}"`).join(`
1
+ /*! @altertable/altertable-js 0.5.3 | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
+ var Altertable=(()=>{var I=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var _e=Object.prototype.hasOwnProperty;var he=(n,e)=>{for(var t in e)I(n,t,{get:e[t],enumerable:!0})},fe=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of pe(e))!_e.call(n,r)&&r!==t&&I(n,r,{get:()=>e[r],enumerable:!(s=de(e,r))||s.enumerable});return n};var Ee=n=>fe(I({},"__esModule",{value:!0}),n);var Ae={};he(Ae,{TrackingConsent:()=>i,altertable:()=>w});function x(n,e){return(...t)=>[n,...t].join(e)}var P="https://api.altertable.ai",S="production",U="localStorage+cookie",me="atbl",T=x(me,"."),c=T("check"),N="session",L="visitor",ve=1e3*60,$=100,V=30*ve,O=1e3,M="$pageview",B="$lib",z="$lib_version",F="$referer",K="$release",q="$url",G="$viewport",i={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},y=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],k=new Set(["[object Object]","0","NaN","none","None","null"]);var h=class{_queue=[];_queueMaxSize;constructor(e){this._queueMaxSize=e}enqueue(e,t,s){this._queue.length>=this._queueMaxSize&&this._queue.shift(),this._queue.push({eventType:e,payload:t,context:s,sentAt:new Date})}flush(){let e=[...this._queue];return this._queue=[],e}clear(){this._queue=[]}getSize(){return this._queue.length}};function o(n,e=()=>{}){return typeof window>"u"?e():n({window})}function Y(){return o(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function a(n,e){if(!n)throw new Error("Invariant failed")}function Q(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v0.5.3 %c\u2022 Debug mode enabled";f.current[e]||(f.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[s,r]=Se(e.event),[g,l]=Te(e.environment),[W,H]=ke(e.timestamp),[J,Z]=be(t);console.groupCollapsed(`[${n}] %c${s}%c [${g}] %c(${W}) %c${J}`,r,l,H,Z);let[ee,te]=b("User ID"),[ne,se]=C(e.user_id??"Not set"),[re,ie]=b("Visitor ID"),[oe,ae]=C(e.visitor_id??"Not set"),[ge,le]=b("Session ID"),[ce,ue]=C(e.session_id??"Not set");console.log(`%c${ee} %c${ne}`,te,se),console.log(`%c${re} %c${oe}`,ie,ae),console.log(`%c${ge} %c${ce}`,le,ue),console.table(e.properties),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!r){f.current[s]=!0;let g=`[${n}] ${s}`;console.warn(g,...t);try{throw new Error(g)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var f={current:{}};function Ie(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function Se(n){return[n,"background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;"]}function Te(n){return[n,`color: ${ye(n)}; font-weight: 400;`]}function ye(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function ke(n){return[Ie(n),"color: #64748b; font-weight: 400;"]}function b(n){return[n,"color: #64748b; font-size: 11px;"]}function C(n){return[n,'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: "SF Mono", "Monaco", monospace; font-size: 11px;']}function be(n){switch(n){case i.GRANTED:return["",""];case i.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case i.PENDING:case i.DISMISSED:return["PENDING","background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];default:return["UNKNOWN","background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"]}}function R(n){if(typeof globalThis.crypto<"u"&&typeof globalThis.crypto.randomUUID=="function")try{return`${n}-${crypto.randomUUID()}`}catch{}return`${n}-${Math.random().toString(36).substring(2)}`}var E=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??i.PENDING,this._sessionData=this._createDefaultSessionData()}init(){let e=this._storage.getItem(this._storageKey);if(!e){this._sessionData=this._createDefaultSessionData(),this._persistToStorage();return}try{let t=JSON.parse(e);this._sessionData={visitorId:t.visitorId||this._generateVisitorId(),sessionId:t.sessionId||this._generateSessionId(),userId:t.userId||null,lastEventAt:t.lastEventAt||null,trackingConsent:Ce(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getVisitorId(){return this._sessionData.visitorId}getSessionId(){return this._sessionData.sessionId}getUserId(){return this._sessionData.userId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}setUserId(e){this._sessionData.userId=e,this._persistToStorage()}setTrackingConsent(e){this._sessionData.trackingConsent=e,this._persistToStorage()}updateLastEventAt(e){this._sessionData.lastEventAt=e,this._persistToStorage()}renewSessionIfNeeded(){return this._shouldRenewSession()?(this._renewSession(),this._persistToStorage(),!0):!1}reset({resetVisitorId:e=!1,resetSessionId:t=!0,resetTrackingConsent:s=!1}={}){e&&(this._sessionData.visitorId=this._generateVisitorId()),t&&(this._sessionData.sessionId=this._generateSessionId()),s&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.userId=null,this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{visitorId:this._generateVisitorId(),sessionId:this._generateSessionId(),userId:null,lastEventAt:null,trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return R(N)}_generateVisitorId(){return R(L)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),s=new Date(e).getTime();return t-s>V}_renewSession(){this._sessionData.sessionId=this._generateSessionId(),this._sessionData.lastEventAt=null}_persistToStorage(){try{this._storage.setItem(this._storageKey,JSON.stringify(this._sessionData))}catch{this._logger.warnDev("Failed to persist session data to storage.")}}};function Ce(n){return typeof n=="string"&&Object.values(i).includes(n)}function D(n,e,t){for(let s of t){let r=e.getItem(s);r!==null&&(n.setItem(s,r),e.removeItem(s))}}var u=class{store={};getItem(e){return this.store[e]??null}setItem(e,t){this.store[e]=t}removeItem(e){delete this.store[e]}migrate(e,t){D(this,e,t)}},_=class{getItem(e){return o(({window:t})=>{let s=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return s?decodeURIComponent(s[2]):null},()=>null)}setItem(e,t){o(({window:s})=>{s.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){o(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){D(this,e,t)}},d=class{constructor(e){this.storage=e}getItem(e){return o(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){o(({window:s})=>{try{s[this.storage].setItem(e,t)}catch{}})}removeItem(e){o(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){D(this,e,t)}},A=class{localStore=new d("localStorage");cookieStore=new _;getItem(e){return this.localStore.getItem(e)??this.cookieStore.getItem(e)}setItem(e,t){this.localStore.setItem(e,t),this.cookieStore.setItem(e,t)}removeItem(e){this.localStore.removeItem(e),this.cookieStore.removeItem(e)}migrate(e,t){for(let s of t){let r=e.getItem(s);r!==null&&(this.localStore.setItem(s,r),this.cookieStore.setItem(s,r))}for(let s of t)e.removeItem(s)}};function p(n){return o(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${c}=1`;let t=e.document.cookie.indexOf(`${c}=`)!==-1;return e.document.cookie=`${c}=; Max-Age=0`,t}else return e[n].setItem(c,"1"),e[n].removeItem(c),!0}catch{return!1}},()=>!1)}function m(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return p("localStorage")?new d("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),m("localStorage+cookie",e));case"localStorage+cookie":{let s=p("localStorage"),r=p("cookie");return s&&r?new A:r?(t("localStorage+cookie not fully supported, falling back to cookie."),new _):s?(t("cookie not supported, falling back to localStorage."),new d("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new u)}case"sessionStorage":return p("sessionStorage")?new d("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new u);case"cookie":return p("cookie")?new _:(t("cookie not supported, falling back to memory."),new u);case"memory":return new u;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Re=[...y,...k].map(n=>`- "${n}"`).join(`
3
3
  `),X=`List of reserved identifiers:
4
4
  ${Re}`;function j(n){if(!n||n.trim()==="")throw new Error("User ID cannot be empty or contain only whitespace.");if(y.some(s=>n.toLowerCase()===s.toLowerCase()))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
5
5
 
6
6
  `+X);if(k.has(n))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
7
7
 
8
- `+X)}var v=class{_apiKey;_cleanupAutoCapture;_config;_eventQueue;_isInitialized=!1;_lastUrl;_logger=Q("Altertable");_referrer;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._eventQueue=new h(O)}init(e,t={}){a(e,"Missing API key"),this._apiKey=e,this._config=t,this._storageKey=T(e,this._config.environment||S),this._referrer=o(({window:r})=>r.document.referrer||null,()=>null),this._lastUrl=o(({window:r})=>r.location.href||null,()=>null);let s=t.persistence??U;return this._storage=m(s,{onFallback:r=>this._logger.warn(r)}),this._sessionManager=new E({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:t.trackingConsent??i.PENDING}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader(),this._handleAutoCaptureChange(t.autoCapture??!0),()=>{this._cleanupAutoCapture?.()}}configure(e){if(a(this._isInitialized,"The client must be initialized with init() before configuring."),e.autoCapture!==void 0&&e.autoCapture!==this._config.autoCapture&&this._handleAutoCaptureChange(e.autoCapture),e.persistence!==void 0&&e.persistence!==this._config.persistence){let s=this._storage;this._storage=m(e.persistence,{onFallback:r=>this._logger.warn(r)}),this._storage.migrate(s,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();if(e.trackingConsent!==void 0&&e.trackingConsent!==t)if(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==i.GRANTED&&e.trackingConsent===i.GRANTED){let s=this._eventQueue.flush();s.length>0&&s.forEach(r=>{this._processEvent(r.eventType,r.payload,r.context)})}else e.trackingConsent===i.DENIED&&this._eventQueue.clear();this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),s=setInterval(t,$);o(({window:r})=>{r.addEventListener("popstate",t),r.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(s),o(({window:r})=>{r.removeEventListener("popstate",t),r.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){a(this._isInitialized,"The client must be initialized with init() before identifying users.");try{j(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}this._sessionManager.setUserId(e);let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:t,user_id:e,visitor_id:s.visitor_id},s)}updateTraits(e){let t=this._sessionManager.getUserId();a(t,"User must be identified with identify() before updating traits.");let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:e,user_id:t,visitor_id:s.visitor_id},s)}reset({resetVisitorId:e=!1,resetSessionId:t=!0}={}){a(this._isInitialized,"The client must be initialized with init() before resetting."),this._sessionManager.reset({resetVisitorId:e,resetSessionId:t})}page(e){a(this._isInitialized,"The client must be initialized with init() before tracking page views.");let t=new URL(e),s=`${t.origin}${t.pathname}`;this.track(M,{[q]:s,[G]:Y(),[F]:this._referrer,...Object.fromEntries(t.searchParams)})}track(e,t={}){a(this._isInitialized,"The client must be initialized with init() before tracking events."),this._sessionManager.renewSessionIfNeeded();let s=new Date().toISOString();this._sessionManager.updateLastEventAt(s);let r=this._getEventContext(),g={timestamp:s,event:e,environment:r.environment,user_id:r.user_id,session_id:r.session_id,visitor_id:r.visitor_id,properties:{[B]:"@altertable/altertable-js",[z]:"0.5.2",[K]:this._config.release,...t}};if(this._processEvent("track",g,r),this._config.debug){let l=this._sessionManager.getTrackingConsent();this._logger.logEvent(g,{trackingConsent:l})}}getTrackingConsent(){return this._sessionManager.getTrackingConsent()}_checkForChanges(){o(({window:e})=>{if(!this._config.autoCapture)return;let t=e.location.href;t!==this._lastUrl&&(this.page(t),this._referrer=this._lastUrl,this._lastUrl=t)})}_getEventContext(){return{environment:this._config.environment||S,user_id:this._sessionManager.getUserId(),visitor_id:this._sessionManager.getVisitorId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t,s){switch(this._sessionManager.getTrackingConsent()){case i.GRANTED:this._request(`/${e}`,t);break;case i.PENDING:case i.DISMISSED:this._eventQueue.enqueue(e,t,s);break;case i.DENIED:break}}_request(e,t){a(this._apiKey,"Missing API key"),a(this._config,"Missing configuration");let s=`${this._config.baseUrl||P}${e}`,r=JSON.stringify(t);if(typeof navigator<"u"&&navigator.sendBeacon){let g=`${s}?apiKey=${encodeURIComponent(this._apiKey)}`,l=new Blob([r],{type:"application/json"});navigator.sendBeacon(g,l)}else fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:r})}};var w=new v;o(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let s=t[0],r=t.slice(1);w[s](...r)}n.Altertable=w});return Ee(Ae);})();
8
+ `+X)}var v=class{_apiKey;_cleanupAutoCapture;_config;_eventQueue;_isInitialized=!1;_lastUrl;_logger=Q("Altertable");_referrer;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._eventQueue=new h(O)}init(e,t={}){a(e,"Missing API key"),this._apiKey=e,this._config=t,this._storageKey=T(e,this._config.environment||S),this._referrer=o(({window:r})=>r.document.referrer||null,()=>null),this._lastUrl=o(({window:r})=>r.location.href||null,()=>null);let s=t.persistence??U;return this._storage=m(s,{onFallback:r=>this._logger.warn(r)}),this._sessionManager=new E({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:t.trackingConsent??i.PENDING}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader(),this._handleAutoCaptureChange(t.autoCapture??!0),()=>{this._cleanupAutoCapture?.()}}configure(e){if(a(this._isInitialized,"The client must be initialized with init() before configuring."),e.autoCapture!==void 0&&e.autoCapture!==this._config.autoCapture&&this._handleAutoCaptureChange(e.autoCapture),e.persistence!==void 0&&e.persistence!==this._config.persistence){let s=this._storage;this._storage=m(e.persistence,{onFallback:r=>this._logger.warn(r)}),this._storage.migrate(s,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();if(e.trackingConsent!==void 0&&e.trackingConsent!==t)if(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==i.GRANTED&&e.trackingConsent===i.GRANTED){let s=this._eventQueue.flush();s.length>0&&s.forEach(r=>{this._processEvent(r.eventType,r.payload,r.context)})}else e.trackingConsent===i.DENIED&&this._eventQueue.clear();this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),s=setInterval(t,$);o(({window:r})=>{r.addEventListener("popstate",t),r.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(s),o(({window:r})=>{r.removeEventListener("popstate",t),r.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){a(this._isInitialized,"The client must be initialized with init() before identifying users.");try{j(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}this._sessionManager.setUserId(e);let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:t,user_id:e,visitor_id:s.visitor_id},s)}updateTraits(e){let t=this._sessionManager.getUserId();a(t,"User must be identified with identify() before updating traits.");let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:e,user_id:t,visitor_id:s.visitor_id},s)}reset({resetVisitorId:e=!1,resetSessionId:t=!0}={}){a(this._isInitialized,"The client must be initialized with init() before resetting."),this._sessionManager.reset({resetVisitorId:e,resetSessionId:t})}page(e){a(this._isInitialized,"The client must be initialized with init() before tracking page views.");let t=new URL(e),s=`${t.origin}${t.pathname}`;this.track(M,{[q]:s,[G]:Y(),[F]:this._referrer,...Object.fromEntries(t.searchParams)})}track(e,t={}){a(this._isInitialized,"The client must be initialized with init() before tracking events."),this._sessionManager.renewSessionIfNeeded();let s=new Date().toISOString();this._sessionManager.updateLastEventAt(s);let r=this._getEventContext(),g={timestamp:s,event:e,environment:r.environment,user_id:r.user_id,session_id:r.session_id,visitor_id:r.visitor_id,properties:{[B]:"@altertable/altertable-js",[z]:"0.5.3",[K]:this._config.release,...t}};if(this._processEvent("track",g,r),this._config.debug){let l=this._sessionManager.getTrackingConsent();this._logger.logEvent(g,{trackingConsent:l})}}getTrackingConsent(){return this._sessionManager.getTrackingConsent()}_checkForChanges(){o(({window:e})=>{let t=e.location.href;t!==this._lastUrl&&(this.page(t),this._referrer=this._lastUrl,this._lastUrl=t)})}_getEventContext(){return{environment:this._config.environment||S,user_id:this._sessionManager.getUserId(),visitor_id:this._sessionManager.getVisitorId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t,s){switch(this._sessionManager.getTrackingConsent()){case i.GRANTED:this._request(`/${e}`,t);break;case i.PENDING:case i.DISMISSED:this._eventQueue.enqueue(e,t,s);break;case i.DENIED:break}}_request(e,t){a(this._apiKey,"Missing API key"),a(this._config,"Missing configuration");let s=`${this._config.baseUrl||P}${e}`,r=JSON.stringify(t);if(typeof navigator<"u"&&navigator.sendBeacon){let g=`${s}?apiKey=${encodeURIComponent(this._apiKey)}`,l=new Blob([r],{type:"application/json"});navigator.sendBeacon(g,l)}else fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:r})}};var w=new v;o(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let s=t[0],r=t.slice(1);w[s](...r)}n.Altertable=w});return Ee(Ae);})();
9
9
  //# sourceMappingURL=index.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/createKeyBuilder.ts","../src/constants.ts","../src/lib/eventQueue.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/getViewport.ts","../src/lib/invariant.ts","../src/lib/logger.ts","../src/lib/generateId.ts","../src/lib/sessionManager.ts","../src/lib/storage.ts","../src/lib/validateUserId.ts","../src/core.ts"],"sourcesContent":["import { TrackingConsent } from './constants';\nimport { Altertable, type AltertableConfig } from './core';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\n\nexport type { Altertable, AltertableConfig };\nexport { TrackingConsent };\n\ndeclare global {\n interface Window {\n Altertable: Altertable | Array<Array<unknown>> | undefined;\n }\n}\n\nexport const altertable = new Altertable();\n\nsafelyRunOnBrowser(({ window }) => {\n const stub = window.Altertable;\n if (stub && Array.isArray(stub)) {\n for (const item of stub) {\n const method = item[0];\n const args = item.slice(1);\n (altertable[method as keyof Altertable] as any)(...args);\n }\n }\n\n window.Altertable = altertable;\n});\n","export function createKeyBuilder(prefix: string, separator: string) {\n return (...parts: string[]) => {\n return [prefix, ...parts].join(separator);\n };\n}\n","import { createKeyBuilder } from './lib/createKeyBuilder';\n\nexport const DEFAULT_BASE_URL = 'https://api.altertable.ai';\nexport const DEFAULT_ENVIRONMENT = 'production';\nexport const DEFAULT_PERSISTENCE = 'localStorage+cookie';\n\nconst STORAGE_KEY_PREFIX = 'atbl';\nexport const keyBuilder = createKeyBuilder(STORAGE_KEY_PREFIX, '.');\nexport const STORAGE_KEY_TEST = keyBuilder('check');\n\nexport const PREFIX_SESSION_ID = 'session';\nexport const PREFIX_VISITOR_ID = 'visitor';\n\nconst MINUTE_IN_MS = 1000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_EVENT_QUEUE_SIZE = 1000;\n\nexport const EVENT_PAGEVIEW = '$pageview';\n\nexport const PROPERTY_LIB = '$lib';\nexport const PROPERTY_LIB_VERSION = '$lib_version';\nexport const PROPERTY_REFERER = '$referer';\nexport const PROPERTY_RELEASE = '$release';\nexport const PROPERTY_URL = '$url';\nexport const PROPERTY_VIEWPORT = '$viewport';\n\nexport const TrackingConsent = {\n DENIED: 'denied',\n DISMISSED: 'dismissed',\n GRANTED: 'granted',\n PENDING: 'pending',\n} as const;\n\nexport type TrackingConsentType =\n (typeof TrackingConsent)[keyof typeof TrackingConsent];\n\nexport const RESERVED_USER_IDS = [\n 'anonymous_id',\n 'anonymous',\n 'distinct_id',\n 'distinctid',\n 'false',\n 'guest',\n 'id',\n 'not_authenticated',\n 'true',\n 'undefined',\n 'user_id',\n 'user',\n 'visitor_id',\n 'visitor',\n];\nexport const RESERVED_USER_IDS_CASE_SENSITIVE = new Set([\n '[object Object]',\n '0',\n 'NaN',\n 'none',\n 'None',\n 'null',\n]);\n","import type { EventContext, EventType } from '../types';\n\ntype QueuedEvent<TPayload> = {\n eventType: EventType;\n payload: TPayload;\n sentAt: Date;\n context: EventContext;\n};\n\nexport class EventQueue<TPayload> {\n private _queue: QueuedEvent<TPayload>[] = [];\n private _queueMaxSize: number;\n\n constructor(queueMaxSize: number) {\n this._queueMaxSize = queueMaxSize;\n }\n\n enqueue(\n eventType: 'track' | 'identify',\n payload: TPayload,\n context: EventContext\n ): void {\n if (this._queue.length >= this._queueMaxSize) {\n // Remove oldest event to make room for new one\n this._queue.shift();\n }\n this._queue.push({\n eventType,\n payload,\n context,\n sentAt: new Date(),\n });\n }\n\n flush(): Array<QueuedEvent<TPayload>> {\n const events = [...this._queue];\n this._queue = [];\n return events;\n }\n\n clear(): void {\n this._queue = [];\n }\n\n getSize(): number {\n return this._queue.length;\n }\n}\n","/* eslint-disable no-restricted-globals */\n\n/** Runs code on browser environments safely. */\nexport function safelyRunOnBrowser<TReturn>(\n callback: (params: { window: typeof window }) => TReturn,\n /** Fallback to run on server environments. */\n fallback: () => TReturn = () => undefined as unknown as TReturn\n): TReturn {\n if (typeof window === 'undefined') {\n return fallback();\n }\n\n return callback({ window });\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport function getViewport(): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","/**\n * Throws an error if the condition is not met.\n *\n * The error is exhaustive in development, and becomes generic in production.\n *\n * This is used to make development a better experience to provide guidance as\n * to where the error comes from.\n */\nexport function invariant(\n condition: unknown,\n message: string | (() => string)\n): asserts condition {\n if (condition) {\n return;\n }\n\n if (__DEV__) {\n throw new Error(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n }\n\n throw new Error('Invariant failed');\n}\n","/* eslint-disable no-console */\n\nimport { TrackingConsent, TrackingConsentType } from '../constants';\nimport { EventPayload } from '../types';\n\nexport type Logger = ReturnType<typeof createLogger>;\n\nexport function createLogger(prefix: string) {\n return {\n log: (...args: unknown[]) => {\n console.log(`[${prefix}]`, ...args);\n },\n logHeader: () => {\n const header = `Altertable v${__LIB_VERSION__} %c• Debug mode enabled`;\n const hasAlreadyPrinted = loggerCache.current[header];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[header] = true;\n console.log(header, 'color: #64748b;');\n }\n },\n logEvent: (\n payload: EventPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event\n );\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [timestampLabel, timestampStyle] = createTimestampElement(\n payload.timestamp\n );\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c [${environmentBadgeLabel}] %c(${timestampLabel}) %c${consentBadgeLabel}`,\n eventBadgeStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabelLabel, userLabelStyle] = createLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.user_id ?? 'Not set'\n );\n const [visitorLabelLabel, visitorLabelStyle] =\n createLabelElement('Visitor ID');\n const [visitorValueLabel, visitorValueStyle] = createValueElement(\n payload.visitor_id ?? 'Not set'\n );\n const [sessionLabelLabel, sessionLabelStyle] =\n createLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabelLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${visitorLabelLabel} %c${visitorValueLabel}`,\n visitorLabelStyle,\n visitorValueStyle\n );\n console.log(\n `%c${sessionLabelLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n warn: (...args: unknown[]) => {\n console.warn(`[${prefix}]`, ...args);\n },\n warnDev: (message: string, ...args: unknown[]) => {\n if (!__DEV__) {\n return;\n }\n\n const sanitizedMessage = message.trim();\n const hasAlreadyPrinted = loggerCache.current[sanitizedMessage];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[sanitizedMessage] = true;\n const warning = `[${prefix}] ${sanitizedMessage}`;\n\n console.warn(warning, ...args);\n\n try {\n // Welcome to debugging Altertable.\n //\n // This error was thrown as a convenience so that you can find the source\n // of the warning that appears in the console by enabling \"Pause on exceptions\"\n // in your debugger.\n throw new Error(warning);\n } catch (error) {\n // Do nothing\n }\n }\n },\n error: (...args: unknown[]) => {\n console.error(`[${prefix}]`, ...args);\n },\n };\n}\n\nexport const loggerCache: { current: Record<string, boolean> } = {\n current: {},\n};\n\nfunction formatEventTime(timestamp: string) {\n return new Date(timestamp).toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction createEventBadgeElement(value: string): [string, string] {\n return [\n value,\n 'background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;',\n ];\n}\n\nfunction createEnvironmentBadgeElement(value: string): [string, string] {\n return [value, `color: ${getEnvironmentColor(value)}; font-weight: 400;`];\n}\n\nfunction getEnvironmentColor(environment: string) {\n const formattedEnv = environment.toLocaleLowerCase().startsWith('prod')\n ? 'production'\n : environment;\n\n switch (formattedEnv) {\n case 'production':\n return '#ef4444';\n default:\n return '#3b82f6';\n }\n}\n\nfunction createTimestampElement(value: string): [string, string] {\n return [formatEventTime(value), 'color: #64748b; font-weight: 400;'];\n}\n\nfunction createLabelElement(value: string): [string, string] {\n return [value, 'color: #64748b; font-size: 11px;'];\n}\n\nfunction createValueElement(value: string): [string, string] {\n return [\n value,\n 'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: \"SF Mono\", \"Monaco\", monospace; font-size: 11px;',\n ];\n}\n\nfunction getConsentBadgeElement(\n trackingConsent: TrackingConsentType\n): [string, string] {\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n return ['', ''];\n case TrackingConsent.DENIED:\n return [\n 'DENIED',\n 'background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n return [\n 'PENDING',\n 'background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n default:\n return [\n 'UNKNOWN',\n 'background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n }\n}\n","export function generateId<T extends string>(prefix: T): `${T}-${string}` {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n try {\n return `${prefix}-${crypto.randomUUID()}`;\n } catch {\n // Continue with Math.random() fallback.\n }\n }\n return `${prefix}-${Math.random().toString(36).substring(2)}`;\n}\n","import {\n PREFIX_SESSION_ID,\n PREFIX_VISITOR_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\nimport type { UserId, VisitorId, SessionId } from '../types';\n\ntype SessionData = {\n visitorId: VisitorId;\n sessionId: SessionId;\n userId: UserId | null;\n lastEventAt: string | null;\n trackingConsent: TrackingConsentType;\n};\n\nexport class SessionManager {\n private _defaultTrackingConsent: TrackingConsentType;\n private _logger: Logger;\n private _sessionData: SessionData;\n private _storage: StorageApi;\n private _storageKey: string;\n\n constructor(options: {\n storage: StorageApi;\n storageKey: string;\n logger: Logger;\n defaultTrackingConsent: TrackingConsentType;\n }) {\n this._storage = options.storage;\n this._storageKey = options.storageKey;\n this._logger = options.logger;\n this._defaultTrackingConsent =\n options.defaultTrackingConsent ?? TrackingConsent.PENDING;\n this._sessionData = this._createDefaultSessionData();\n }\n\n init(): void {\n const storedData = this._storage.getItem(this._storageKey);\n\n if (!storedData) {\n this._sessionData = this._createDefaultSessionData();\n this._persistToStorage();\n return;\n }\n\n try {\n const parsedData = JSON.parse(storedData) as Partial<SessionData>;\n\n this._sessionData = {\n visitorId: parsedData.visitorId || this._generateVisitorId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n userId: parsedData.userId || null,\n lastEventAt: parsedData.lastEventAt || null,\n trackingConsent: isValidTrackingConsent(parsedData.trackingConsent)\n ? parsedData.trackingConsent\n : this._defaultTrackingConsent,\n };\n } catch (error) {\n this._logger.warnDev(\n 'Failed to parse storage data. Resetting session data.'\n );\n this._sessionData = this._createDefaultSessionData();\n }\n\n this._persistToStorage();\n }\n\n getVisitorId(): VisitorId {\n return this._sessionData.visitorId;\n }\n\n getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getUserId(): UserId | null {\n return this._sessionData.userId;\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n setUserId(userId: UserId | null): void {\n this._sessionData.userId = userId;\n this._persistToStorage();\n }\n\n setTrackingConsent(consent: TrackingConsentType): void {\n this._sessionData.trackingConsent = consent;\n this._persistToStorage();\n }\n\n updateLastEventAt(timestamp: string): void {\n this._sessionData.lastEventAt = timestamp;\n this._persistToStorage();\n }\n\n renewSessionIfNeeded(): boolean {\n const shouldRenew = this._shouldRenewSession();\n\n if (shouldRenew) {\n this._renewSession();\n this._persistToStorage();\n return true;\n }\n\n return false;\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n resetTrackingConsent = false,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetVisitorId) {\n this._sessionData.visitorId = this._generateVisitorId();\n }\n\n if (resetSessionId) {\n this._sessionData.sessionId = this._generateSessionId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.userId = null;\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n visitorId: this._generateVisitorId(),\n sessionId: this._generateSessionId(),\n userId: null,\n lastEventAt: null,\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateVisitorId(): VisitorId {\n return generateId(PREFIX_VISITOR_ID);\n }\n\n private _shouldRenewSession(): boolean {\n const { lastEventAt } = this._sessionData;\n\n if (!lastEventAt) {\n return true;\n }\n\n const now = new Date().getTime();\n const lastEventTime = new Date(lastEventAt).getTime();\n const timeSinceLastEvent = now - lastEventTime;\n\n return timeSinceLastEvent > SESSION_EXPIRATION_TIME_MS;\n }\n\n private _renewSession(): void {\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.lastEventAt = null;\n }\n\n private _persistToStorage(): void {\n try {\n this._storage.setItem(\n this._storageKey,\n JSON.stringify(this._sessionData)\n );\n } catch (error) {\n this._logger.warnDev('Failed to persist session data to storage.');\n }\n }\n}\n\nfunction isValidTrackingConsent(value: unknown): value is TrackingConsentType {\n return (\n typeof value === 'string' &&\n Object.values(TrackingConsent).includes(value as TrackingConsentType)\n );\n}\n","import { STORAGE_KEY_TEST } from '../constants';\nimport { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport type StorageType =\n | 'localStorage'\n | 'sessionStorage'\n | 'cookie'\n | 'memory'\n | 'localStorage+cookie';\n\nexport interface StorageApi {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n migrate(fromStorage: StorageApi, keys: string[]): void;\n}\n\nfunction migrateKeys(\n toStorage: StorageApi,\n fromStorage: StorageApi,\n keys: string[]\n): void {\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n toStorage.setItem(key, value);\n fromStorage.removeItem(key);\n }\n }\n}\n\nclass MemoryStore implements StorageApi {\n private store: Record<string, string> = {};\n getItem(key: string): string | null {\n return this.store[key] ?? null;\n }\n setItem(key: string, value: string) {\n this.store[key] = value;\n }\n removeItem(key: string) {\n delete this.store[key];\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass CookieStore implements StorageApi {\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n const match = window.document.cookie.match(\n new RegExp('(^| )' + key + '=([^;]+)')\n );\n return match ? decodeURIComponent(match[2]) : null;\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=${encodeURIComponent(value)}; path=/;`;\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=; Max-Age=0; path=/;`;\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass WebStorageStore implements StorageApi {\n constructor(private storage: 'localStorage' | 'sessionStorage') {}\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n try {\n return window[this.storage].getItem(key);\n } catch {\n return null;\n }\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].setItem(key, value);\n } catch {\n /* ignore */\n }\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].removeItem(key);\n } catch {\n /* ignore */\n }\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass LocalPlusCookieStore implements StorageApi {\n private localStore = new WebStorageStore('localStorage');\n private cookieStore = new CookieStore();\n getItem(key: string): string | null {\n return this.localStore.getItem(key) ?? this.cookieStore.getItem(key);\n }\n setItem(key: string, value: string) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n removeItem(key: string) {\n this.localStore.removeItem(key);\n this.cookieStore.removeItem(key);\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n // Migrate to both localStorage and cookie without removing from source yet\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n }\n\n for (const key of keys) {\n fromStorage.removeItem(key);\n }\n }\n}\n\nfunction testStorageSupport(\n storageType: 'localStorage' | 'sessionStorage' | 'cookie'\n) {\n return safelyRunOnBrowser(\n ({ window }) => {\n try {\n if (storageType === 'cookie') {\n window.document.cookie = `${STORAGE_KEY_TEST}=1`;\n const supported =\n window.document.cookie.indexOf(`${STORAGE_KEY_TEST}=`) !== -1;\n window.document.cookie = `${STORAGE_KEY_TEST}=; Max-Age=0`;\n return supported;\n } else {\n window[storageType].setItem(STORAGE_KEY_TEST, '1');\n window[storageType].removeItem(STORAGE_KEY_TEST);\n return true;\n }\n } catch {\n return false;\n }\n },\n () => false\n );\n}\n\nexport function selectStorage(\n type: StorageType | 'unknown',\n params: { onFallback: (message: string) => void }\n): StorageApi {\n const { onFallback } = params;\n\n switch (type) {\n case 'localStorage': {\n if (testStorageSupport('localStorage')) {\n return new WebStorageStore('localStorage');\n }\n onFallback(\n 'localStorage not supported, falling back to localStorage+cookie.'\n );\n return selectStorage('localStorage+cookie', params);\n }\n\n case 'localStorage+cookie': {\n const localStorageSupported = testStorageSupport('localStorage');\n const cookieSupported = testStorageSupport('cookie');\n\n if (localStorageSupported && cookieSupported) {\n return new LocalPlusCookieStore();\n } else if (cookieSupported) {\n onFallback(\n 'localStorage+cookie not fully supported, falling back to cookie.'\n );\n return new CookieStore();\n } else if (localStorageSupported) {\n onFallback('cookie not supported, falling back to localStorage.');\n return new WebStorageStore('localStorage');\n } else {\n onFallback(\n 'Neither localStorage nor cookie supported, falling back to memory.'\n );\n return new MemoryStore();\n }\n }\n\n case 'sessionStorage': {\n if (testStorageSupport('sessionStorage')) {\n return new WebStorageStore('sessionStorage');\n }\n onFallback('sessionStorage not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'cookie': {\n if (testStorageSupport('cookie')) {\n return new CookieStore();\n }\n onFallback('cookie not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'memory': {\n return new MemoryStore();\n }\n\n default: {\n throw new Error(\n `Unknown storage type: \"${type}\". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`\n );\n }\n }\n}\n","import {\n RESERVED_USER_IDS,\n RESERVED_USER_IDS_CASE_SENSITIVE,\n} from '../constants';\n\nconst reservedIdentifiersList = [\n ...RESERVED_USER_IDS,\n ...RESERVED_USER_IDS_CASE_SENSITIVE,\n]\n .map(id => `- \"${id}\"`)\n .join('\\n');\nconst reservedIdentifiersInfo = `List of reserved identifiers:\\n${reservedIdentifiersList}`;\n\nexport function validateUserId(userId: string): void {\n if (!userId || userId.trim() === '') {\n throw new Error('User ID cannot be empty or contain only whitespace.');\n }\n\n const isCaseInsensitiveBlocked = RESERVED_USER_IDS.some(\n blockedId => userId.toLowerCase() === blockedId.toLowerCase()\n );\n\n if (isCaseInsensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n\n const isCaseSensitiveBlocked = RESERVED_USER_IDS_CASE_SENSITIVE.has(userId);\n\n if (isCaseSensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n}\n","import {\n AUTO_CAPTURE_INTERVAL_MS,\n DEFAULT_BASE_URL,\n DEFAULT_ENVIRONMENT,\n DEFAULT_PERSISTENCE,\n EVENT_PAGEVIEW,\n keyBuilder,\n MAX_EVENT_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { EventQueue } from './lib/eventQueue';\nimport { getViewport } from './lib/getViewport';\nimport { invariant } from './lib/invariant';\nimport { createLogger } from './lib/logger';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\nimport { SessionManager } from './lib/sessionManager';\nimport {\n selectStorage,\n type StorageApi,\n type StorageType,\n} from './lib/storage';\nimport { validateUserId } from './lib/validateUserId';\nimport {\n EventContext,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n UserTraits,\n} from './types';\n\nexport interface AltertableConfig {\n /**\n * The base URL of the Altertable API.\n * @default https://api.altertable.ai\n */\n baseUrl?: string;\n /**\n * The environment of the application.\n * @default \"production\"\n */\n environment?: string;\n /**\n * Whether to automatically capture page views and events.\n * @default true\n */\n autoCapture?: boolean;\n /**\n * The release ID of the application.\n * This is helpful to identify the version of the application an event is coming from.\n */\n release?: string;\n /**\n * Whether to log events to the console.\n * @default false\n */\n debug?: boolean;\n /**\n * The persistence strategy for storing IDs.\n * @default \"localStorage+cookie\"\n */\n persistence?: StorageType;\n /**\n * The tracking consent state.\n * @default \"pending\"\n */\n trackingConsent?: TrackingConsentType;\n}\n\nexport class Altertable {\n private _apiKey: string;\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _eventQueue: EventQueue<EventPayload | IdentifyPayload>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _sessionManager: SessionManager | undefined;\n private _storage: StorageApi | undefined;\n private _storageKey: string | undefined;\n\n constructor() {\n this._lastUrl = null;\n this._referrer = null;\n this._eventQueue = new EventQueue(MAX_EVENT_QUEUE_SIZE);\n }\n\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._apiKey = apiKey;\n this._config = config;\n this._storageKey = keyBuilder(\n apiKey,\n this._config.environment || DEFAULT_ENVIRONMENT\n );\n this._referrer = safelyRunOnBrowser<string | null>(\n ({ window }) => window.document.referrer || null,\n () => null\n );\n this._lastUrl = safelyRunOnBrowser<string | null>(\n ({ window }) => window.location.href || null,\n () => null\n );\n const persistence: StorageType = config.persistence ?? DEFAULT_PERSISTENCE;\n this._storage = selectStorage(persistence, {\n onFallback: message => this._logger.warn(message),\n });\n\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: config.trackingConsent ?? TrackingConsent.PENDING,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n this._handleAutoCaptureChange(config.autoCapture ?? true);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n configure(updates: Partial<AltertableConfig>) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before configuring.'\n );\n\n if (\n updates.autoCapture !== undefined &&\n updates.autoCapture !== this._config.autoCapture\n ) {\n this._handleAutoCaptureChange(updates.autoCapture);\n }\n\n if (\n updates.persistence !== undefined &&\n updates.persistence !== this._config.persistence\n ) {\n const previousStorage = this._storage;\n this._storage = selectStorage(updates.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._storage.migrate(previousStorage, [this._storageKey]);\n }\n\n const currentTrackingConsent = this._sessionManager.getTrackingConsent();\n if (\n updates.trackingConsent !== undefined &&\n updates.trackingConsent !== currentTrackingConsent\n ) {\n this._sessionManager.setTrackingConsent(updates.trackingConsent);\n\n if (\n currentTrackingConsent !== TrackingConsent.GRANTED &&\n updates.trackingConsent === TrackingConsent.GRANTED\n ) {\n const queuedEvents = this._eventQueue.flush();\n if (queuedEvents.length > 0) {\n queuedEvents.forEach(event => {\n this._processEvent(event.eventType, event.payload, event.context);\n });\n }\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._eventQueue.clear();\n }\n }\n\n this._config = { ...this._config, ...updates };\n }\n\n private _handleAutoCaptureChange(enableAutoCapture: boolean) {\n this._cleanupAutoCapture?.();\n\n if (enableAutoCapture) {\n if (this._lastUrl) {\n this.page(this._lastUrl);\n }\n\n const checkForChanges = this._checkForChanges.bind(this);\n const intervalId = setInterval(checkForChanges, AUTO_CAPTURE_INTERVAL_MS);\n\n safelyRunOnBrowser(({ window }) => {\n window.addEventListener('popstate', checkForChanges);\n window.addEventListener('hashchange', checkForChanges);\n });\n\n this._cleanupAutoCapture = () => {\n clearInterval(intervalId);\n safelyRunOnBrowser(({ window }) => {\n window.removeEventListener('popstate', checkForChanges);\n window.removeEventListener('hashchange', checkForChanges);\n });\n };\n } else {\n this._cleanupAutoCapture = undefined;\n }\n }\n\n identify(userId: string, traits: UserTraits = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before identifying users.'\n );\n\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n this._sessionManager.setUserId(userId);\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n updateTraits(traits: UserTraits) {\n const userId = this._sessionManager.getUserId();\n invariant(\n userId,\n 'User must be identified with identify() before updating traits.'\n );\n\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n } = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before resetting.'\n );\n\n this._sessionManager.reset({ resetVisitorId, resetSessionId });\n }\n\n page(url: string) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking page views.'\n );\n\n const parsedUrl = new URL(url);\n const urlWithoutSearch = `${parsedUrl.origin}${parsedUrl.pathname}`;\n this.track(EVENT_PAGEVIEW, {\n [PROPERTY_URL]: urlWithoutSearch,\n [PROPERTY_VIEWPORT]: getViewport(),\n [PROPERTY_REFERER]: this._referrer,\n ...Object.fromEntries(parsedUrl.searchParams),\n });\n }\n\n track(event: string, properties: EventProperties = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking events.'\n );\n\n this._sessionManager.renewSessionIfNeeded();\n const timestamp = new Date().toISOString();\n this._sessionManager.updateLastEventAt(timestamp);\n\n const context = this._getEventContext();\n const payload: EventPayload = {\n timestamp,\n event,\n environment: context.environment,\n user_id: context.user_id,\n session_id: context.session_id,\n visitor_id: context.visitor_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...properties,\n },\n };\n\n this._processEvent('track', payload, context);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionManager.getTrackingConsent();\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n if (!this._config.autoCapture) {\n return;\n }\n\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this.page(currentUrl);\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n }\n });\n }\n\n private _getEventContext(): EventContext {\n return {\n environment: this._config.environment || DEFAULT_ENVIRONMENT,\n user_id: this._sessionManager.getUserId(),\n visitor_id: this._sessionManager.getVisitorId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload | IdentifyPayload>(\n eventType: EventType,\n payload: TPayload,\n context: EventContext\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._request(`/${eventType}`, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._eventQueue.enqueue(eventType, payload, context);\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private _request(path: string, body: unknown): void {\n invariant(this._apiKey, 'Missing API key');\n invariant(this._config, 'Missing configuration');\n\n const url = `${this._config.baseUrl || DEFAULT_BASE_URL}${path}`;\n const payload = JSON.stringify(body);\n\n /* eslint-disable no-restricted-globals */\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n const beaconUrl = `${url}?apiKey=${encodeURIComponent(this._apiKey)}`;\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(beaconUrl, blob);\n } /* eslint-enable no-restricted-globals */ else {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._apiKey}`,\n },\n body: payload,\n });\n }\n }\n}\n"],"mappings":"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","names":["index_exports","__export","TrackingConsent","altertable","createKeyBuilder","prefix","separator","parts","DEFAULT_BASE_URL","DEFAULT_ENVIRONMENT","DEFAULT_PERSISTENCE","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_EVENT_QUEUE_SIZE","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","EventQueue","queueMaxSize","eventType","payload","context","events","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","invariant","condition","message","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabelLabel","userLabelStyle","createLabelElement","userValueLabel","userValueStyle","createValueElement","visitorLabelLabel","visitorLabelStyle","visitorValueLabel","visitorValueStyle","sessionLabelLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","value","getEnvironmentColor","environment","TrackingConsent","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetVisitorId","resetSessionId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","lastEventAt","now","lastEventTime","SESSION_EXPIRATION_TIME_MS","value","migrateKeys","toStorage","fromStorage","keys","key","value","MemoryStore","CookieStore","safelyRunOnBrowser","window","match","WebStorageStore","storage","LocalPlusCookieStore","testStorageSupport","storageType","STORAGE_KEY_TEST","supported","selectStorage","type","params","onFallback","localStorageSupported","cookieSupported","reservedIdentifiersList","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","id","reservedIdentifiersInfo","validateUserId","userId","blockedId","Altertable","createLogger","EventQueue","MAX_EVENT_QUEUE_SIZE","apiKey","config","invariant","keyBuilder","DEFAULT_ENVIRONMENT","safelyRunOnBrowser","window","persistence","DEFAULT_PERSISTENCE","selectStorage","message","SessionManager","TrackingConsent","updates","previousStorage","currentTrackingConsent","queuedEvents","event","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","resetVisitorId","resetSessionId","url","parsedUrl","urlWithoutSearch","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","getViewport","PROPERTY_REFERER","properties","timestamp","payload","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","trackingConsent","currentUrl","eventType","path","body","DEFAULT_BASE_URL","beaconUrl","blob","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/createKeyBuilder.ts","../src/constants.ts","../src/lib/eventQueue.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/getViewport.ts","../src/lib/invariant.ts","../src/lib/logger.ts","../src/lib/generateId.ts","../src/lib/sessionManager.ts","../src/lib/storage.ts","../src/lib/validateUserId.ts","../src/core.ts"],"sourcesContent":["import { TrackingConsent } from './constants';\nimport { Altertable, type AltertableConfig } from './core';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\n\nexport type { Altertable, AltertableConfig };\nexport { TrackingConsent };\n\ndeclare global {\n interface Window {\n Altertable: Altertable | Array<Array<unknown>> | undefined;\n }\n}\n\nexport const altertable = new Altertable();\n\nsafelyRunOnBrowser(({ window }) => {\n const stub = window.Altertable;\n if (stub && Array.isArray(stub)) {\n for (const item of stub) {\n const method = item[0];\n const args = item.slice(1);\n (altertable[method as keyof Altertable] as any)(...args);\n }\n }\n\n window.Altertable = altertable;\n});\n","export function createKeyBuilder(prefix: string, separator: string) {\n return (...parts: string[]) => {\n return [prefix, ...parts].join(separator);\n };\n}\n","import { createKeyBuilder } from './lib/createKeyBuilder';\n\nexport const DEFAULT_BASE_URL = 'https://api.altertable.ai';\nexport const DEFAULT_ENVIRONMENT = 'production';\nexport const DEFAULT_PERSISTENCE = 'localStorage+cookie';\n\nconst STORAGE_KEY_PREFIX = 'atbl';\nexport const keyBuilder = createKeyBuilder(STORAGE_KEY_PREFIX, '.');\nexport const STORAGE_KEY_TEST = keyBuilder('check');\n\nexport const PREFIX_SESSION_ID = 'session';\nexport const PREFIX_VISITOR_ID = 'visitor';\n\nconst MINUTE_IN_MS = 1000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_EVENT_QUEUE_SIZE = 1000;\n\nexport const EVENT_PAGEVIEW = '$pageview';\n\nexport const PROPERTY_LIB = '$lib';\nexport const PROPERTY_LIB_VERSION = '$lib_version';\nexport const PROPERTY_REFERER = '$referer';\nexport const PROPERTY_RELEASE = '$release';\nexport const PROPERTY_URL = '$url';\nexport const PROPERTY_VIEWPORT = '$viewport';\n\nexport const TrackingConsent = {\n DENIED: 'denied',\n DISMISSED: 'dismissed',\n GRANTED: 'granted',\n PENDING: 'pending',\n} as const;\n\nexport type TrackingConsentType =\n (typeof TrackingConsent)[keyof typeof TrackingConsent];\n\nexport const RESERVED_USER_IDS = [\n 'anonymous_id',\n 'anonymous',\n 'distinct_id',\n 'distinctid',\n 'false',\n 'guest',\n 'id',\n 'not_authenticated',\n 'true',\n 'undefined',\n 'user_id',\n 'user',\n 'visitor_id',\n 'visitor',\n];\nexport const RESERVED_USER_IDS_CASE_SENSITIVE = new Set([\n '[object Object]',\n '0',\n 'NaN',\n 'none',\n 'None',\n 'null',\n]);\n","import type { EventContext, EventType } from '../types';\n\ntype QueuedEvent<TPayload> = {\n eventType: EventType;\n payload: TPayload;\n sentAt: Date;\n context: EventContext;\n};\n\nexport class EventQueue<TPayload> {\n private _queue: QueuedEvent<TPayload>[] = [];\n private _queueMaxSize: number;\n\n constructor(queueMaxSize: number) {\n this._queueMaxSize = queueMaxSize;\n }\n\n enqueue(\n eventType: 'track' | 'identify',\n payload: TPayload,\n context: EventContext\n ): void {\n if (this._queue.length >= this._queueMaxSize) {\n // Remove oldest event to make room for new one\n this._queue.shift();\n }\n this._queue.push({\n eventType,\n payload,\n context,\n sentAt: new Date(),\n });\n }\n\n flush(): Array<QueuedEvent<TPayload>> {\n const events = [...this._queue];\n this._queue = [];\n return events;\n }\n\n clear(): void {\n this._queue = [];\n }\n\n getSize(): number {\n return this._queue.length;\n }\n}\n","/* eslint-disable no-restricted-globals */\n\n/** Runs code on browser environments safely. */\nexport function safelyRunOnBrowser<TReturn>(\n callback: (params: { window: typeof window }) => TReturn,\n /** Fallback to run on server environments. */\n fallback: () => TReturn = () => undefined as unknown as TReturn\n): TReturn {\n if (typeof window === 'undefined') {\n return fallback();\n }\n\n return callback({ window });\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport function getViewport(): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","/**\n * Throws an error if the condition is not met.\n *\n * The error is exhaustive in development, and becomes generic in production.\n *\n * This is used to make development a better experience to provide guidance as\n * to where the error comes from.\n */\nexport function invariant(\n condition: unknown,\n message: string | (() => string)\n): asserts condition {\n if (condition) {\n return;\n }\n\n if (__DEV__) {\n throw new Error(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n }\n\n throw new Error('Invariant failed');\n}\n","/* eslint-disable no-console */\n\nimport { TrackingConsent, TrackingConsentType } from '../constants';\nimport { EventPayload } from '../types';\n\nexport type Logger = ReturnType<typeof createLogger>;\n\nexport function createLogger(prefix: string) {\n return {\n log: (...args: unknown[]) => {\n console.log(`[${prefix}]`, ...args);\n },\n logHeader: () => {\n const header = `Altertable v${__LIB_VERSION__} %c• Debug mode enabled`;\n const hasAlreadyPrinted = loggerCache.current[header];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[header] = true;\n console.log(header, 'color: #64748b;');\n }\n },\n logEvent: (\n payload: EventPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event\n );\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [timestampLabel, timestampStyle] = createTimestampElement(\n payload.timestamp\n );\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c [${environmentBadgeLabel}] %c(${timestampLabel}) %c${consentBadgeLabel}`,\n eventBadgeStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabelLabel, userLabelStyle] = createLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.user_id ?? 'Not set'\n );\n const [visitorLabelLabel, visitorLabelStyle] =\n createLabelElement('Visitor ID');\n const [visitorValueLabel, visitorValueStyle] = createValueElement(\n payload.visitor_id ?? 'Not set'\n );\n const [sessionLabelLabel, sessionLabelStyle] =\n createLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabelLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${visitorLabelLabel} %c${visitorValueLabel}`,\n visitorLabelStyle,\n visitorValueStyle\n );\n console.log(\n `%c${sessionLabelLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n warn: (...args: unknown[]) => {\n console.warn(`[${prefix}]`, ...args);\n },\n warnDev: (message: string, ...args: unknown[]) => {\n if (!__DEV__) {\n return;\n }\n\n const sanitizedMessage = message.trim();\n const hasAlreadyPrinted = loggerCache.current[sanitizedMessage];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[sanitizedMessage] = true;\n const warning = `[${prefix}] ${sanitizedMessage}`;\n\n console.warn(warning, ...args);\n\n try {\n // Welcome to debugging Altertable.\n //\n // This error was thrown as a convenience so that you can find the source\n // of the warning that appears in the console by enabling \"Pause on exceptions\"\n // in your debugger.\n throw new Error(warning);\n } catch (error) {\n // Do nothing\n }\n }\n },\n error: (...args: unknown[]) => {\n console.error(`[${prefix}]`, ...args);\n },\n };\n}\n\nexport const loggerCache: { current: Record<string, boolean> } = {\n current: {},\n};\n\nfunction formatEventTime(timestamp: string) {\n return new Date(timestamp).toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction createEventBadgeElement(value: string): [string, string] {\n return [\n value,\n 'background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;',\n ];\n}\n\nfunction createEnvironmentBadgeElement(value: string): [string, string] {\n return [value, `color: ${getEnvironmentColor(value)}; font-weight: 400;`];\n}\n\nfunction getEnvironmentColor(environment: string) {\n const formattedEnv = environment.toLocaleLowerCase().startsWith('prod')\n ? 'production'\n : environment;\n\n switch (formattedEnv) {\n case 'production':\n return '#ef4444';\n default:\n return '#3b82f6';\n }\n}\n\nfunction createTimestampElement(value: string): [string, string] {\n return [formatEventTime(value), 'color: #64748b; font-weight: 400;'];\n}\n\nfunction createLabelElement(value: string): [string, string] {\n return [value, 'color: #64748b; font-size: 11px;'];\n}\n\nfunction createValueElement(value: string): [string, string] {\n return [\n value,\n 'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: \"SF Mono\", \"Monaco\", monospace; font-size: 11px;',\n ];\n}\n\nfunction getConsentBadgeElement(\n trackingConsent: TrackingConsentType\n): [string, string] {\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n return ['', ''];\n case TrackingConsent.DENIED:\n return [\n 'DENIED',\n 'background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n return [\n 'PENDING',\n 'background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n default:\n return [\n 'UNKNOWN',\n 'background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n }\n}\n","export function generateId<T extends string>(prefix: T): `${T}-${string}` {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n try {\n return `${prefix}-${crypto.randomUUID()}`;\n } catch {\n // Continue with Math.random() fallback.\n }\n }\n return `${prefix}-${Math.random().toString(36).substring(2)}`;\n}\n","import {\n PREFIX_SESSION_ID,\n PREFIX_VISITOR_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\nimport type { UserId, VisitorId, SessionId } from '../types';\n\ntype SessionData = {\n visitorId: VisitorId;\n sessionId: SessionId;\n userId: UserId | null;\n lastEventAt: string | null;\n trackingConsent: TrackingConsentType;\n};\n\nexport class SessionManager {\n private _defaultTrackingConsent: TrackingConsentType;\n private _logger: Logger;\n private _sessionData: SessionData;\n private _storage: StorageApi;\n private _storageKey: string;\n\n constructor(options: {\n storage: StorageApi;\n storageKey: string;\n logger: Logger;\n defaultTrackingConsent: TrackingConsentType;\n }) {\n this._storage = options.storage;\n this._storageKey = options.storageKey;\n this._logger = options.logger;\n this._defaultTrackingConsent =\n options.defaultTrackingConsent ?? TrackingConsent.PENDING;\n this._sessionData = this._createDefaultSessionData();\n }\n\n init(): void {\n const storedData = this._storage.getItem(this._storageKey);\n\n if (!storedData) {\n this._sessionData = this._createDefaultSessionData();\n this._persistToStorage();\n return;\n }\n\n try {\n const parsedData = JSON.parse(storedData) as Partial<SessionData>;\n\n this._sessionData = {\n visitorId: parsedData.visitorId || this._generateVisitorId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n userId: parsedData.userId || null,\n lastEventAt: parsedData.lastEventAt || null,\n trackingConsent: isValidTrackingConsent(parsedData.trackingConsent)\n ? parsedData.trackingConsent\n : this._defaultTrackingConsent,\n };\n } catch (error) {\n this._logger.warnDev(\n 'Failed to parse storage data. Resetting session data.'\n );\n this._sessionData = this._createDefaultSessionData();\n }\n\n this._persistToStorage();\n }\n\n getVisitorId(): VisitorId {\n return this._sessionData.visitorId;\n }\n\n getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getUserId(): UserId | null {\n return this._sessionData.userId;\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n setUserId(userId: UserId | null): void {\n this._sessionData.userId = userId;\n this._persistToStorage();\n }\n\n setTrackingConsent(consent: TrackingConsentType): void {\n this._sessionData.trackingConsent = consent;\n this._persistToStorage();\n }\n\n updateLastEventAt(timestamp: string): void {\n this._sessionData.lastEventAt = timestamp;\n this._persistToStorage();\n }\n\n renewSessionIfNeeded(): boolean {\n const shouldRenew = this._shouldRenewSession();\n\n if (shouldRenew) {\n this._renewSession();\n this._persistToStorage();\n return true;\n }\n\n return false;\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n resetTrackingConsent = false,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetVisitorId) {\n this._sessionData.visitorId = this._generateVisitorId();\n }\n\n if (resetSessionId) {\n this._sessionData.sessionId = this._generateSessionId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.userId = null;\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n visitorId: this._generateVisitorId(),\n sessionId: this._generateSessionId(),\n userId: null,\n lastEventAt: null,\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateVisitorId(): VisitorId {\n return generateId(PREFIX_VISITOR_ID);\n }\n\n private _shouldRenewSession(): boolean {\n const { lastEventAt } = this._sessionData;\n\n if (!lastEventAt) {\n return true;\n }\n\n const now = new Date().getTime();\n const lastEventTime = new Date(lastEventAt).getTime();\n const timeSinceLastEvent = now - lastEventTime;\n\n return timeSinceLastEvent > SESSION_EXPIRATION_TIME_MS;\n }\n\n private _renewSession(): void {\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.lastEventAt = null;\n }\n\n private _persistToStorage(): void {\n try {\n this._storage.setItem(\n this._storageKey,\n JSON.stringify(this._sessionData)\n );\n } catch (error) {\n this._logger.warnDev('Failed to persist session data to storage.');\n }\n }\n}\n\nfunction isValidTrackingConsent(value: unknown): value is TrackingConsentType {\n return (\n typeof value === 'string' &&\n Object.values(TrackingConsent).includes(value as TrackingConsentType)\n );\n}\n","import { STORAGE_KEY_TEST } from '../constants';\nimport { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport type StorageType =\n | 'localStorage'\n | 'sessionStorage'\n | 'cookie'\n | 'memory'\n | 'localStorage+cookie';\n\nexport interface StorageApi {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n migrate(fromStorage: StorageApi, keys: string[]): void;\n}\n\nfunction migrateKeys(\n toStorage: StorageApi,\n fromStorage: StorageApi,\n keys: string[]\n): void {\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n toStorage.setItem(key, value);\n fromStorage.removeItem(key);\n }\n }\n}\n\nclass MemoryStore implements StorageApi {\n private store: Record<string, string> = {};\n getItem(key: string): string | null {\n return this.store[key] ?? null;\n }\n setItem(key: string, value: string) {\n this.store[key] = value;\n }\n removeItem(key: string) {\n delete this.store[key];\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass CookieStore implements StorageApi {\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n const match = window.document.cookie.match(\n new RegExp('(^| )' + key + '=([^;]+)')\n );\n return match ? decodeURIComponent(match[2]) : null;\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=${encodeURIComponent(value)}; path=/;`;\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=; Max-Age=0; path=/;`;\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass WebStorageStore implements StorageApi {\n constructor(private storage: 'localStorage' | 'sessionStorage') {}\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n try {\n return window[this.storage].getItem(key);\n } catch {\n return null;\n }\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].setItem(key, value);\n } catch {\n /* ignore */\n }\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].removeItem(key);\n } catch {\n /* ignore */\n }\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass LocalPlusCookieStore implements StorageApi {\n private localStore = new WebStorageStore('localStorage');\n private cookieStore = new CookieStore();\n getItem(key: string): string | null {\n return this.localStore.getItem(key) ?? this.cookieStore.getItem(key);\n }\n setItem(key: string, value: string) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n removeItem(key: string) {\n this.localStore.removeItem(key);\n this.cookieStore.removeItem(key);\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n // Migrate to both localStorage and cookie without removing from source yet\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n }\n\n for (const key of keys) {\n fromStorage.removeItem(key);\n }\n }\n}\n\nfunction testStorageSupport(\n storageType: 'localStorage' | 'sessionStorage' | 'cookie'\n) {\n return safelyRunOnBrowser(\n ({ window }) => {\n try {\n if (storageType === 'cookie') {\n window.document.cookie = `${STORAGE_KEY_TEST}=1`;\n const supported =\n window.document.cookie.indexOf(`${STORAGE_KEY_TEST}=`) !== -1;\n window.document.cookie = `${STORAGE_KEY_TEST}=; Max-Age=0`;\n return supported;\n } else {\n window[storageType].setItem(STORAGE_KEY_TEST, '1');\n window[storageType].removeItem(STORAGE_KEY_TEST);\n return true;\n }\n } catch {\n return false;\n }\n },\n () => false\n );\n}\n\nexport function selectStorage(\n type: StorageType | 'unknown',\n params: { onFallback: (message: string) => void }\n): StorageApi {\n const { onFallback } = params;\n\n switch (type) {\n case 'localStorage': {\n if (testStorageSupport('localStorage')) {\n return new WebStorageStore('localStorage');\n }\n onFallback(\n 'localStorage not supported, falling back to localStorage+cookie.'\n );\n return selectStorage('localStorage+cookie', params);\n }\n\n case 'localStorage+cookie': {\n const localStorageSupported = testStorageSupport('localStorage');\n const cookieSupported = testStorageSupport('cookie');\n\n if (localStorageSupported && cookieSupported) {\n return new LocalPlusCookieStore();\n } else if (cookieSupported) {\n onFallback(\n 'localStorage+cookie not fully supported, falling back to cookie.'\n );\n return new CookieStore();\n } else if (localStorageSupported) {\n onFallback('cookie not supported, falling back to localStorage.');\n return new WebStorageStore('localStorage');\n } else {\n onFallback(\n 'Neither localStorage nor cookie supported, falling back to memory.'\n );\n return new MemoryStore();\n }\n }\n\n case 'sessionStorage': {\n if (testStorageSupport('sessionStorage')) {\n return new WebStorageStore('sessionStorage');\n }\n onFallback('sessionStorage not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'cookie': {\n if (testStorageSupport('cookie')) {\n return new CookieStore();\n }\n onFallback('cookie not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'memory': {\n return new MemoryStore();\n }\n\n default: {\n throw new Error(\n `Unknown storage type: \"${type}\". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`\n );\n }\n }\n}\n","import {\n RESERVED_USER_IDS,\n RESERVED_USER_IDS_CASE_SENSITIVE,\n} from '../constants';\n\nconst reservedIdentifiersList = [\n ...RESERVED_USER_IDS,\n ...RESERVED_USER_IDS_CASE_SENSITIVE,\n]\n .map(id => `- \"${id}\"`)\n .join('\\n');\nconst reservedIdentifiersInfo = `List of reserved identifiers:\\n${reservedIdentifiersList}`;\n\nexport function validateUserId(userId: string): void {\n if (!userId || userId.trim() === '') {\n throw new Error('User ID cannot be empty or contain only whitespace.');\n }\n\n const isCaseInsensitiveBlocked = RESERVED_USER_IDS.some(\n blockedId => userId.toLowerCase() === blockedId.toLowerCase()\n );\n\n if (isCaseInsensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n\n const isCaseSensitiveBlocked = RESERVED_USER_IDS_CASE_SENSITIVE.has(userId);\n\n if (isCaseSensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n}\n","import {\n AUTO_CAPTURE_INTERVAL_MS,\n DEFAULT_BASE_URL,\n DEFAULT_ENVIRONMENT,\n DEFAULT_PERSISTENCE,\n EVENT_PAGEVIEW,\n keyBuilder,\n MAX_EVENT_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { EventQueue } from './lib/eventQueue';\nimport { getViewport } from './lib/getViewport';\nimport { invariant } from './lib/invariant';\nimport { createLogger } from './lib/logger';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\nimport { SessionManager } from './lib/sessionManager';\nimport {\n selectStorage,\n type StorageApi,\n type StorageType,\n} from './lib/storage';\nimport { validateUserId } from './lib/validateUserId';\nimport {\n EventContext,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n UserTraits,\n} from './types';\n\nexport interface AltertableConfig {\n /**\n * The base URL of the Altertable API.\n * @default https://api.altertable.ai\n */\n baseUrl?: string;\n /**\n * The environment of the application.\n * @default \"production\"\n */\n environment?: string;\n /**\n * Whether to automatically capture page views and events.\n * @default true\n */\n autoCapture?: boolean;\n /**\n * The release ID of the application.\n * This is helpful to identify the version of the application an event is coming from.\n */\n release?: string;\n /**\n * Whether to log events to the console.\n * @default false\n */\n debug?: boolean;\n /**\n * The persistence strategy for storing IDs.\n * @default \"localStorage+cookie\"\n */\n persistence?: StorageType;\n /**\n * The tracking consent state.\n * @default \"pending\"\n */\n trackingConsent?: TrackingConsentType;\n}\n\nexport class Altertable {\n private _apiKey: string;\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _eventQueue: EventQueue<EventPayload | IdentifyPayload>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _sessionManager: SessionManager | undefined;\n private _storage: StorageApi | undefined;\n private _storageKey: string | undefined;\n\n constructor() {\n this._lastUrl = null;\n this._referrer = null;\n this._eventQueue = new EventQueue(MAX_EVENT_QUEUE_SIZE);\n }\n\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._apiKey = apiKey;\n this._config = config;\n this._storageKey = keyBuilder(\n apiKey,\n this._config.environment || DEFAULT_ENVIRONMENT\n );\n this._referrer = safelyRunOnBrowser<string | null>(\n ({ window }) => window.document.referrer || null,\n () => null\n );\n this._lastUrl = safelyRunOnBrowser<string | null>(\n ({ window }) => window.location.href || null,\n () => null\n );\n const persistence: StorageType = config.persistence ?? DEFAULT_PERSISTENCE;\n this._storage = selectStorage(persistence, {\n onFallback: message => this._logger.warn(message),\n });\n\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: config.trackingConsent ?? TrackingConsent.PENDING,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n this._handleAutoCaptureChange(config.autoCapture ?? true);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n configure(updates: Partial<AltertableConfig>) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before configuring.'\n );\n\n if (\n updates.autoCapture !== undefined &&\n updates.autoCapture !== this._config.autoCapture\n ) {\n this._handleAutoCaptureChange(updates.autoCapture);\n }\n\n if (\n updates.persistence !== undefined &&\n updates.persistence !== this._config.persistence\n ) {\n const previousStorage = this._storage;\n this._storage = selectStorage(updates.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._storage.migrate(previousStorage, [this._storageKey]);\n }\n\n const currentTrackingConsent = this._sessionManager.getTrackingConsent();\n if (\n updates.trackingConsent !== undefined &&\n updates.trackingConsent !== currentTrackingConsent\n ) {\n this._sessionManager.setTrackingConsent(updates.trackingConsent);\n\n if (\n currentTrackingConsent !== TrackingConsent.GRANTED &&\n updates.trackingConsent === TrackingConsent.GRANTED\n ) {\n const queuedEvents = this._eventQueue.flush();\n if (queuedEvents.length > 0) {\n queuedEvents.forEach(event => {\n this._processEvent(event.eventType, event.payload, event.context);\n });\n }\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._eventQueue.clear();\n }\n }\n\n this._config = { ...this._config, ...updates };\n }\n\n private _handleAutoCaptureChange(enableAutoCapture: boolean) {\n this._cleanupAutoCapture?.();\n\n if (enableAutoCapture) {\n if (this._lastUrl) {\n this.page(this._lastUrl);\n }\n\n const checkForChanges = this._checkForChanges.bind(this);\n const intervalId = setInterval(checkForChanges, AUTO_CAPTURE_INTERVAL_MS);\n\n safelyRunOnBrowser(({ window }) => {\n window.addEventListener('popstate', checkForChanges);\n window.addEventListener('hashchange', checkForChanges);\n });\n\n this._cleanupAutoCapture = () => {\n clearInterval(intervalId);\n safelyRunOnBrowser(({ window }) => {\n window.removeEventListener('popstate', checkForChanges);\n window.removeEventListener('hashchange', checkForChanges);\n });\n };\n } else {\n this._cleanupAutoCapture = undefined;\n }\n }\n\n identify(userId: string, traits: UserTraits = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before identifying users.'\n );\n\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n this._sessionManager.setUserId(userId);\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n updateTraits(traits: UserTraits) {\n const userId = this._sessionManager.getUserId();\n invariant(\n userId,\n 'User must be identified with identify() before updating traits.'\n );\n\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n } = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before resetting.'\n );\n\n this._sessionManager.reset({ resetVisitorId, resetSessionId });\n }\n\n page(url: string) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking page views.'\n );\n\n const parsedUrl = new URL(url);\n const urlWithoutSearch = `${parsedUrl.origin}${parsedUrl.pathname}`;\n this.track(EVENT_PAGEVIEW, {\n [PROPERTY_URL]: urlWithoutSearch,\n [PROPERTY_VIEWPORT]: getViewport(),\n [PROPERTY_REFERER]: this._referrer,\n ...Object.fromEntries(parsedUrl.searchParams),\n });\n }\n\n track(event: string, properties: EventProperties = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking events.'\n );\n\n this._sessionManager.renewSessionIfNeeded();\n const timestamp = new Date().toISOString();\n this._sessionManager.updateLastEventAt(timestamp);\n\n const context = this._getEventContext();\n const payload: EventPayload = {\n timestamp,\n event,\n environment: context.environment,\n user_id: context.user_id,\n session_id: context.session_id,\n visitor_id: context.visitor_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...properties,\n },\n };\n\n this._processEvent('track', payload, context);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionManager.getTrackingConsent();\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this.page(currentUrl);\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n }\n });\n }\n\n private _getEventContext(): EventContext {\n return {\n environment: this._config.environment || DEFAULT_ENVIRONMENT,\n user_id: this._sessionManager.getUserId(),\n visitor_id: this._sessionManager.getVisitorId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload | IdentifyPayload>(\n eventType: EventType,\n payload: TPayload,\n context: EventContext\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._request(`/${eventType}`, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._eventQueue.enqueue(eventType, payload, context);\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private _request(path: string, body: unknown): void {\n invariant(this._apiKey, 'Missing API key');\n invariant(this._config, 'Missing configuration');\n\n const url = `${this._config.baseUrl || DEFAULT_BASE_URL}${path}`;\n const payload = JSON.stringify(body);\n\n /* eslint-disable no-restricted-globals */\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n const beaconUrl = `${url}?apiKey=${encodeURIComponent(this._apiKey)}`;\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(beaconUrl, blob);\n } /* eslint-enable no-restricted-globals */ else {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._apiKey}`,\n },\n body: payload,\n });\n }\n }\n}\n"],"mappings":"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","names":["index_exports","__export","TrackingConsent","altertable","createKeyBuilder","prefix","separator","parts","DEFAULT_BASE_URL","DEFAULT_ENVIRONMENT","DEFAULT_PERSISTENCE","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_EVENT_QUEUE_SIZE","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","EventQueue","queueMaxSize","eventType","payload","context","events","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","invariant","condition","message","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabelLabel","userLabelStyle","createLabelElement","userValueLabel","userValueStyle","createValueElement","visitorLabelLabel","visitorLabelStyle","visitorValueLabel","visitorValueStyle","sessionLabelLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","value","getEnvironmentColor","environment","TrackingConsent","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetVisitorId","resetSessionId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","lastEventAt","now","lastEventTime","SESSION_EXPIRATION_TIME_MS","value","migrateKeys","toStorage","fromStorage","keys","key","value","MemoryStore","CookieStore","safelyRunOnBrowser","window","match","WebStorageStore","storage","LocalPlusCookieStore","testStorageSupport","storageType","STORAGE_KEY_TEST","supported","selectStorage","type","params","onFallback","localStorageSupported","cookieSupported","reservedIdentifiersList","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","id","reservedIdentifiersInfo","validateUserId","userId","blockedId","Altertable","createLogger","EventQueue","MAX_EVENT_QUEUE_SIZE","apiKey","config","invariant","keyBuilder","DEFAULT_ENVIRONMENT","safelyRunOnBrowser","window","persistence","DEFAULT_PERSISTENCE","selectStorage","message","SessionManager","TrackingConsent","updates","previousStorage","currentTrackingConsent","queuedEvents","event","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","resetVisitorId","resetSessionId","url","parsedUrl","urlWithoutSearch","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","getViewport","PROPERTY_REFERER","properties","timestamp","payload","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","trackingConsent","currentUrl","eventType","path","body","DEFAULT_BASE_URL","beaconUrl","blob","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- /*! @altertable/altertable-js 0.5.2 | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
- var I=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var _e=Object.prototype.hasOwnProperty;var he=(n,e)=>{for(var t in e)I(n,t,{get:e[t],enumerable:!0})},fe=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of pe(e))!_e.call(n,r)&&r!==t&&I(n,r,{get:()=>e[r],enumerable:!(s=de(e,r))||s.enumerable});return n};var Ee=n=>fe(I({},"__esModule",{value:!0}),n);var Ae={};he(Ae,{TrackingConsent:()=>i,altertable:()=>w});module.exports=Ee(Ae);function x(n,e){return(...t)=>[n,...t].join(e)}var P="https://api.altertable.ai",S="production",U="localStorage+cookie",me="atbl",T=x(me,"."),c=T("check"),N="session",L="visitor",ve=1e3*60,$=100,V=30*ve,O=1e3,M="$pageview",B="$lib",z="$lib_version",F="$referer",K="$release",q="$url",G="$viewport",i={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},y=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],k=new Set(["[object Object]","0","NaN","none","None","null"]);var h=class{_queue=[];_queueMaxSize;constructor(e){this._queueMaxSize=e}enqueue(e,t,s){this._queue.length>=this._queueMaxSize&&this._queue.shift(),this._queue.push({eventType:e,payload:t,context:s,sentAt:new Date})}flush(){let e=[...this._queue];return this._queue=[],e}clear(){this._queue=[]}getSize(){return this._queue.length}};function o(n,e=()=>{}){return typeof window>"u"?e():n({window})}function Y(){return o(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function a(n,e){if(!n)throw new Error("Invariant failed")}function Q(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v0.5.2 %c\u2022 Debug mode enabled";f.current[e]||(f.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[s,r]=Se(e.event),[g,l]=Te(e.environment),[W,H]=ke(e.timestamp),[J,Z]=be(t);console.groupCollapsed(`[${n}] %c${s}%c [${g}] %c(${W}) %c${J}`,r,l,H,Z);let[ee,te]=b("User ID"),[ne,se]=C(e.user_id??"Not set"),[re,ie]=b("Visitor ID"),[oe,ae]=C(e.visitor_id??"Not set"),[ge,le]=b("Session ID"),[ce,ue]=C(e.session_id??"Not set");console.log(`%c${ee} %c${ne}`,te,se),console.log(`%c${re} %c${oe}`,ie,ae),console.log(`%c${ge} %c${ce}`,le,ue),console.table(e.properties),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!r){f.current[s]=!0;let g=`[${n}] ${s}`;console.warn(g,...t);try{throw new Error(g)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var f={current:{}};function Ie(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function Se(n){return[n,"background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;"]}function Te(n){return[n,`color: ${ye(n)}; font-weight: 400;`]}function ye(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function ke(n){return[Ie(n),"color: #64748b; font-weight: 400;"]}function b(n){return[n,"color: #64748b; font-size: 11px;"]}function C(n){return[n,'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: "SF Mono", "Monaco", monospace; font-size: 11px;']}function be(n){switch(n){case i.GRANTED:return["",""];case i.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case i.PENDING:case i.DISMISSED:return["PENDING","background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];default:return["UNKNOWN","background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"]}}function R(n){if(typeof globalThis.crypto<"u"&&typeof globalThis.crypto.randomUUID=="function")try{return`${n}-${crypto.randomUUID()}`}catch{}return`${n}-${Math.random().toString(36).substring(2)}`}var E=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??i.PENDING,this._sessionData=this._createDefaultSessionData()}init(){let e=this._storage.getItem(this._storageKey);if(!e){this._sessionData=this._createDefaultSessionData(),this._persistToStorage();return}try{let t=JSON.parse(e);this._sessionData={visitorId:t.visitorId||this._generateVisitorId(),sessionId:t.sessionId||this._generateSessionId(),userId:t.userId||null,lastEventAt:t.lastEventAt||null,trackingConsent:Ce(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getVisitorId(){return this._sessionData.visitorId}getSessionId(){return this._sessionData.sessionId}getUserId(){return this._sessionData.userId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}setUserId(e){this._sessionData.userId=e,this._persistToStorage()}setTrackingConsent(e){this._sessionData.trackingConsent=e,this._persistToStorage()}updateLastEventAt(e){this._sessionData.lastEventAt=e,this._persistToStorage()}renewSessionIfNeeded(){return this._shouldRenewSession()?(this._renewSession(),this._persistToStorage(),!0):!1}reset({resetVisitorId:e=!1,resetSessionId:t=!0,resetTrackingConsent:s=!1}={}){e&&(this._sessionData.visitorId=this._generateVisitorId()),t&&(this._sessionData.sessionId=this._generateSessionId()),s&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.userId=null,this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{visitorId:this._generateVisitorId(),sessionId:this._generateSessionId(),userId:null,lastEventAt:null,trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return R(N)}_generateVisitorId(){return R(L)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),s=new Date(e).getTime();return t-s>V}_renewSession(){this._sessionData.sessionId=this._generateSessionId(),this._sessionData.lastEventAt=null}_persistToStorage(){try{this._storage.setItem(this._storageKey,JSON.stringify(this._sessionData))}catch{this._logger.warnDev("Failed to persist session data to storage.")}}};function Ce(n){return typeof n=="string"&&Object.values(i).includes(n)}function D(n,e,t){for(let s of t){let r=e.getItem(s);r!==null&&(n.setItem(s,r),e.removeItem(s))}}var u=class{store={};getItem(e){return this.store[e]??null}setItem(e,t){this.store[e]=t}removeItem(e){delete this.store[e]}migrate(e,t){D(this,e,t)}},_=class{getItem(e){return o(({window:t})=>{let s=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return s?decodeURIComponent(s[2]):null},()=>null)}setItem(e,t){o(({window:s})=>{s.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){o(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){D(this,e,t)}},d=class{constructor(e){this.storage=e}getItem(e){return o(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){o(({window:s})=>{try{s[this.storage].setItem(e,t)}catch{}})}removeItem(e){o(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){D(this,e,t)}},A=class{localStore=new d("localStorage");cookieStore=new _;getItem(e){return this.localStore.getItem(e)??this.cookieStore.getItem(e)}setItem(e,t){this.localStore.setItem(e,t),this.cookieStore.setItem(e,t)}removeItem(e){this.localStore.removeItem(e),this.cookieStore.removeItem(e)}migrate(e,t){for(let s of t){let r=e.getItem(s);r!==null&&(this.localStore.setItem(s,r),this.cookieStore.setItem(s,r))}for(let s of t)e.removeItem(s)}};function p(n){return o(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${c}=1`;let t=e.document.cookie.indexOf(`${c}=`)!==-1;return e.document.cookie=`${c}=; Max-Age=0`,t}else return e[n].setItem(c,"1"),e[n].removeItem(c),!0}catch{return!1}},()=>!1)}function m(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return p("localStorage")?new d("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),m("localStorage+cookie",e));case"localStorage+cookie":{let s=p("localStorage"),r=p("cookie");return s&&r?new A:r?(t("localStorage+cookie not fully supported, falling back to cookie."),new _):s?(t("cookie not supported, falling back to localStorage."),new d("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new u)}case"sessionStorage":return p("sessionStorage")?new d("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new u);case"cookie":return p("cookie")?new _:(t("cookie not supported, falling back to memory."),new u);case"memory":return new u;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Re=[...y,...k].map(n=>`- "${n}"`).join(`
1
+ /*! @altertable/altertable-js 0.5.3 | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
+ var I=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var _e=Object.prototype.hasOwnProperty;var he=(n,e)=>{for(var t in e)I(n,t,{get:e[t],enumerable:!0})},fe=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of pe(e))!_e.call(n,r)&&r!==t&&I(n,r,{get:()=>e[r],enumerable:!(s=de(e,r))||s.enumerable});return n};var Ee=n=>fe(I({},"__esModule",{value:!0}),n);var Ae={};he(Ae,{TrackingConsent:()=>i,altertable:()=>w});module.exports=Ee(Ae);function x(n,e){return(...t)=>[n,...t].join(e)}var P="https://api.altertable.ai",S="production",U="localStorage+cookie",me="atbl",T=x(me,"."),c=T("check"),N="session",L="visitor",ve=1e3*60,$=100,V=30*ve,O=1e3,M="$pageview",B="$lib",z="$lib_version",F="$referer",K="$release",q="$url",G="$viewport",i={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},y=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],k=new Set(["[object Object]","0","NaN","none","None","null"]);var h=class{_queue=[];_queueMaxSize;constructor(e){this._queueMaxSize=e}enqueue(e,t,s){this._queue.length>=this._queueMaxSize&&this._queue.shift(),this._queue.push({eventType:e,payload:t,context:s,sentAt:new Date})}flush(){let e=[...this._queue];return this._queue=[],e}clear(){this._queue=[]}getSize(){return this._queue.length}};function o(n,e=()=>{}){return typeof window>"u"?e():n({window})}function Y(){return o(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function a(n,e){if(!n)throw new Error("Invariant failed")}function Q(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v0.5.3 %c\u2022 Debug mode enabled";f.current[e]||(f.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[s,r]=Se(e.event),[g,l]=Te(e.environment),[W,H]=ke(e.timestamp),[J,Z]=be(t);console.groupCollapsed(`[${n}] %c${s}%c [${g}] %c(${W}) %c${J}`,r,l,H,Z);let[ee,te]=b("User ID"),[ne,se]=C(e.user_id??"Not set"),[re,ie]=b("Visitor ID"),[oe,ae]=C(e.visitor_id??"Not set"),[ge,le]=b("Session ID"),[ce,ue]=C(e.session_id??"Not set");console.log(`%c${ee} %c${ne}`,te,se),console.log(`%c${re} %c${oe}`,ie,ae),console.log(`%c${ge} %c${ce}`,le,ue),console.table(e.properties),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!r){f.current[s]=!0;let g=`[${n}] ${s}`;console.warn(g,...t);try{throw new Error(g)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var f={current:{}};function Ie(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function Se(n){return[n,"background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;"]}function Te(n){return[n,`color: ${ye(n)}; font-weight: 400;`]}function ye(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function ke(n){return[Ie(n),"color: #64748b; font-weight: 400;"]}function b(n){return[n,"color: #64748b; font-size: 11px;"]}function C(n){return[n,'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: "SF Mono", "Monaco", monospace; font-size: 11px;']}function be(n){switch(n){case i.GRANTED:return["",""];case i.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case i.PENDING:case i.DISMISSED:return["PENDING","background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];default:return["UNKNOWN","background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"]}}function R(n){if(typeof globalThis.crypto<"u"&&typeof globalThis.crypto.randomUUID=="function")try{return`${n}-${crypto.randomUUID()}`}catch{}return`${n}-${Math.random().toString(36).substring(2)}`}var E=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??i.PENDING,this._sessionData=this._createDefaultSessionData()}init(){let e=this._storage.getItem(this._storageKey);if(!e){this._sessionData=this._createDefaultSessionData(),this._persistToStorage();return}try{let t=JSON.parse(e);this._sessionData={visitorId:t.visitorId||this._generateVisitorId(),sessionId:t.sessionId||this._generateSessionId(),userId:t.userId||null,lastEventAt:t.lastEventAt||null,trackingConsent:Ce(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getVisitorId(){return this._sessionData.visitorId}getSessionId(){return this._sessionData.sessionId}getUserId(){return this._sessionData.userId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}setUserId(e){this._sessionData.userId=e,this._persistToStorage()}setTrackingConsent(e){this._sessionData.trackingConsent=e,this._persistToStorage()}updateLastEventAt(e){this._sessionData.lastEventAt=e,this._persistToStorage()}renewSessionIfNeeded(){return this._shouldRenewSession()?(this._renewSession(),this._persistToStorage(),!0):!1}reset({resetVisitorId:e=!1,resetSessionId:t=!0,resetTrackingConsent:s=!1}={}){e&&(this._sessionData.visitorId=this._generateVisitorId()),t&&(this._sessionData.sessionId=this._generateSessionId()),s&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.userId=null,this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{visitorId:this._generateVisitorId(),sessionId:this._generateSessionId(),userId:null,lastEventAt:null,trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return R(N)}_generateVisitorId(){return R(L)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),s=new Date(e).getTime();return t-s>V}_renewSession(){this._sessionData.sessionId=this._generateSessionId(),this._sessionData.lastEventAt=null}_persistToStorage(){try{this._storage.setItem(this._storageKey,JSON.stringify(this._sessionData))}catch{this._logger.warnDev("Failed to persist session data to storage.")}}};function Ce(n){return typeof n=="string"&&Object.values(i).includes(n)}function D(n,e,t){for(let s of t){let r=e.getItem(s);r!==null&&(n.setItem(s,r),e.removeItem(s))}}var u=class{store={};getItem(e){return this.store[e]??null}setItem(e,t){this.store[e]=t}removeItem(e){delete this.store[e]}migrate(e,t){D(this,e,t)}},_=class{getItem(e){return o(({window:t})=>{let s=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return s?decodeURIComponent(s[2]):null},()=>null)}setItem(e,t){o(({window:s})=>{s.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){o(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){D(this,e,t)}},d=class{constructor(e){this.storage=e}getItem(e){return o(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){o(({window:s})=>{try{s[this.storage].setItem(e,t)}catch{}})}removeItem(e){o(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){D(this,e,t)}},A=class{localStore=new d("localStorage");cookieStore=new _;getItem(e){return this.localStore.getItem(e)??this.cookieStore.getItem(e)}setItem(e,t){this.localStore.setItem(e,t),this.cookieStore.setItem(e,t)}removeItem(e){this.localStore.removeItem(e),this.cookieStore.removeItem(e)}migrate(e,t){for(let s of t){let r=e.getItem(s);r!==null&&(this.localStore.setItem(s,r),this.cookieStore.setItem(s,r))}for(let s of t)e.removeItem(s)}};function p(n){return o(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${c}=1`;let t=e.document.cookie.indexOf(`${c}=`)!==-1;return e.document.cookie=`${c}=; Max-Age=0`,t}else return e[n].setItem(c,"1"),e[n].removeItem(c),!0}catch{return!1}},()=>!1)}function m(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return p("localStorage")?new d("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),m("localStorage+cookie",e));case"localStorage+cookie":{let s=p("localStorage"),r=p("cookie");return s&&r?new A:r?(t("localStorage+cookie not fully supported, falling back to cookie."),new _):s?(t("cookie not supported, falling back to localStorage."),new d("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new u)}case"sessionStorage":return p("sessionStorage")?new d("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new u);case"cookie":return p("cookie")?new _:(t("cookie not supported, falling back to memory."),new u);case"memory":return new u;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Re=[...y,...k].map(n=>`- "${n}"`).join(`
3
3
  `),X=`List of reserved identifiers:
4
4
  ${Re}`;function j(n){if(!n||n.trim()==="")throw new Error("User ID cannot be empty or contain only whitespace.");if(y.some(s=>n.toLowerCase()===s.toLowerCase()))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
5
5
 
6
6
  `+X);if(k.has(n))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
7
7
 
8
- `+X)}var v=class{_apiKey;_cleanupAutoCapture;_config;_eventQueue;_isInitialized=!1;_lastUrl;_logger=Q("Altertable");_referrer;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._eventQueue=new h(O)}init(e,t={}){a(e,"Missing API key"),this._apiKey=e,this._config=t,this._storageKey=T(e,this._config.environment||S),this._referrer=o(({window:r})=>r.document.referrer||null,()=>null),this._lastUrl=o(({window:r})=>r.location.href||null,()=>null);let s=t.persistence??U;return this._storage=m(s,{onFallback:r=>this._logger.warn(r)}),this._sessionManager=new E({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:t.trackingConsent??i.PENDING}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader(),this._handleAutoCaptureChange(t.autoCapture??!0),()=>{this._cleanupAutoCapture?.()}}configure(e){if(a(this._isInitialized,"The client must be initialized with init() before configuring."),e.autoCapture!==void 0&&e.autoCapture!==this._config.autoCapture&&this._handleAutoCaptureChange(e.autoCapture),e.persistence!==void 0&&e.persistence!==this._config.persistence){let s=this._storage;this._storage=m(e.persistence,{onFallback:r=>this._logger.warn(r)}),this._storage.migrate(s,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();if(e.trackingConsent!==void 0&&e.trackingConsent!==t)if(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==i.GRANTED&&e.trackingConsent===i.GRANTED){let s=this._eventQueue.flush();s.length>0&&s.forEach(r=>{this._processEvent(r.eventType,r.payload,r.context)})}else e.trackingConsent===i.DENIED&&this._eventQueue.clear();this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),s=setInterval(t,$);o(({window:r})=>{r.addEventListener("popstate",t),r.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(s),o(({window:r})=>{r.removeEventListener("popstate",t),r.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){a(this._isInitialized,"The client must be initialized with init() before identifying users.");try{j(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}this._sessionManager.setUserId(e);let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:t,user_id:e,visitor_id:s.visitor_id},s)}updateTraits(e){let t=this._sessionManager.getUserId();a(t,"User must be identified with identify() before updating traits.");let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:e,user_id:t,visitor_id:s.visitor_id},s)}reset({resetVisitorId:e=!1,resetSessionId:t=!0}={}){a(this._isInitialized,"The client must be initialized with init() before resetting."),this._sessionManager.reset({resetVisitorId:e,resetSessionId:t})}page(e){a(this._isInitialized,"The client must be initialized with init() before tracking page views.");let t=new URL(e),s=`${t.origin}${t.pathname}`;this.track(M,{[q]:s,[G]:Y(),[F]:this._referrer,...Object.fromEntries(t.searchParams)})}track(e,t={}){a(this._isInitialized,"The client must be initialized with init() before tracking events."),this._sessionManager.renewSessionIfNeeded();let s=new Date().toISOString();this._sessionManager.updateLastEventAt(s);let r=this._getEventContext(),g={timestamp:s,event:e,environment:r.environment,user_id:r.user_id,session_id:r.session_id,visitor_id:r.visitor_id,properties:{[B]:"@altertable/altertable-js",[z]:"0.5.2",[K]:this._config.release,...t}};if(this._processEvent("track",g,r),this._config.debug){let l=this._sessionManager.getTrackingConsent();this._logger.logEvent(g,{trackingConsent:l})}}getTrackingConsent(){return this._sessionManager.getTrackingConsent()}_checkForChanges(){o(({window:e})=>{if(!this._config.autoCapture)return;let t=e.location.href;t!==this._lastUrl&&(this.page(t),this._referrer=this._lastUrl,this._lastUrl=t)})}_getEventContext(){return{environment:this._config.environment||S,user_id:this._sessionManager.getUserId(),visitor_id:this._sessionManager.getVisitorId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t,s){switch(this._sessionManager.getTrackingConsent()){case i.GRANTED:this._request(`/${e}`,t);break;case i.PENDING:case i.DISMISSED:this._eventQueue.enqueue(e,t,s);break;case i.DENIED:break}}_request(e,t){a(this._apiKey,"Missing API key"),a(this._config,"Missing configuration");let s=`${this._config.baseUrl||P}${e}`,r=JSON.stringify(t);if(typeof navigator<"u"&&navigator.sendBeacon){let g=`${s}?apiKey=${encodeURIComponent(this._apiKey)}`,l=new Blob([r],{type:"application/json"});navigator.sendBeacon(g,l)}else fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:r})}};var w=new v;o(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let s=t[0],r=t.slice(1);w[s](...r)}n.Altertable=w});
8
+ `+X)}var v=class{_apiKey;_cleanupAutoCapture;_config;_eventQueue;_isInitialized=!1;_lastUrl;_logger=Q("Altertable");_referrer;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._eventQueue=new h(O)}init(e,t={}){a(e,"Missing API key"),this._apiKey=e,this._config=t,this._storageKey=T(e,this._config.environment||S),this._referrer=o(({window:r})=>r.document.referrer||null,()=>null),this._lastUrl=o(({window:r})=>r.location.href||null,()=>null);let s=t.persistence??U;return this._storage=m(s,{onFallback:r=>this._logger.warn(r)}),this._sessionManager=new E({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:t.trackingConsent??i.PENDING}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader(),this._handleAutoCaptureChange(t.autoCapture??!0),()=>{this._cleanupAutoCapture?.()}}configure(e){if(a(this._isInitialized,"The client must be initialized with init() before configuring."),e.autoCapture!==void 0&&e.autoCapture!==this._config.autoCapture&&this._handleAutoCaptureChange(e.autoCapture),e.persistence!==void 0&&e.persistence!==this._config.persistence){let s=this._storage;this._storage=m(e.persistence,{onFallback:r=>this._logger.warn(r)}),this._storage.migrate(s,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();if(e.trackingConsent!==void 0&&e.trackingConsent!==t)if(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==i.GRANTED&&e.trackingConsent===i.GRANTED){let s=this._eventQueue.flush();s.length>0&&s.forEach(r=>{this._processEvent(r.eventType,r.payload,r.context)})}else e.trackingConsent===i.DENIED&&this._eventQueue.clear();this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),s=setInterval(t,$);o(({window:r})=>{r.addEventListener("popstate",t),r.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(s),o(({window:r})=>{r.removeEventListener("popstate",t),r.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){a(this._isInitialized,"The client must be initialized with init() before identifying users.");try{j(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}this._sessionManager.setUserId(e);let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:t,user_id:e,visitor_id:s.visitor_id},s)}updateTraits(e){let t=this._sessionManager.getUserId();a(t,"User must be identified with identify() before updating traits.");let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:e,user_id:t,visitor_id:s.visitor_id},s)}reset({resetVisitorId:e=!1,resetSessionId:t=!0}={}){a(this._isInitialized,"The client must be initialized with init() before resetting."),this._sessionManager.reset({resetVisitorId:e,resetSessionId:t})}page(e){a(this._isInitialized,"The client must be initialized with init() before tracking page views.");let t=new URL(e),s=`${t.origin}${t.pathname}`;this.track(M,{[q]:s,[G]:Y(),[F]:this._referrer,...Object.fromEntries(t.searchParams)})}track(e,t={}){a(this._isInitialized,"The client must be initialized with init() before tracking events."),this._sessionManager.renewSessionIfNeeded();let s=new Date().toISOString();this._sessionManager.updateLastEventAt(s);let r=this._getEventContext(),g={timestamp:s,event:e,environment:r.environment,user_id:r.user_id,session_id:r.session_id,visitor_id:r.visitor_id,properties:{[B]:"@altertable/altertable-js",[z]:"0.5.3",[K]:this._config.release,...t}};if(this._processEvent("track",g,r),this._config.debug){let l=this._sessionManager.getTrackingConsent();this._logger.logEvent(g,{trackingConsent:l})}}getTrackingConsent(){return this._sessionManager.getTrackingConsent()}_checkForChanges(){o(({window:e})=>{let t=e.location.href;t!==this._lastUrl&&(this.page(t),this._referrer=this._lastUrl,this._lastUrl=t)})}_getEventContext(){return{environment:this._config.environment||S,user_id:this._sessionManager.getUserId(),visitor_id:this._sessionManager.getVisitorId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t,s){switch(this._sessionManager.getTrackingConsent()){case i.GRANTED:this._request(`/${e}`,t);break;case i.PENDING:case i.DISMISSED:this._eventQueue.enqueue(e,t,s);break;case i.DENIED:break}}_request(e,t){a(this._apiKey,"Missing API key"),a(this._config,"Missing configuration");let s=`${this._config.baseUrl||P}${e}`,r=JSON.stringify(t);if(typeof navigator<"u"&&navigator.sendBeacon){let g=`${s}?apiKey=${encodeURIComponent(this._apiKey)}`,l=new Blob([r],{type:"application/json"});navigator.sendBeacon(g,l)}else fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:r})}};var w=new v;o(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let s=t[0],r=t.slice(1);w[s](...r)}n.Altertable=w});
9
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/createKeyBuilder.ts","../src/constants.ts","../src/lib/eventQueue.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/getViewport.ts","../src/lib/invariant.ts","../src/lib/logger.ts","../src/lib/generateId.ts","../src/lib/sessionManager.ts","../src/lib/storage.ts","../src/lib/validateUserId.ts","../src/core.ts"],"sourcesContent":["import { TrackingConsent } from './constants';\nimport { Altertable, type AltertableConfig } from './core';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\n\nexport type { Altertable, AltertableConfig };\nexport { TrackingConsent };\n\ndeclare global {\n interface Window {\n Altertable: Altertable | Array<Array<unknown>> | undefined;\n }\n}\n\nexport const altertable = new Altertable();\n\nsafelyRunOnBrowser(({ window }) => {\n const stub = window.Altertable;\n if (stub && Array.isArray(stub)) {\n for (const item of stub) {\n const method = item[0];\n const args = item.slice(1);\n (altertable[method as keyof Altertable] as any)(...args);\n }\n }\n\n window.Altertable = altertable;\n});\n","export function createKeyBuilder(prefix: string, separator: string) {\n return (...parts: string[]) => {\n return [prefix, ...parts].join(separator);\n };\n}\n","import { createKeyBuilder } from './lib/createKeyBuilder';\n\nexport const DEFAULT_BASE_URL = 'https://api.altertable.ai';\nexport const DEFAULT_ENVIRONMENT = 'production';\nexport const DEFAULT_PERSISTENCE = 'localStorage+cookie';\n\nconst STORAGE_KEY_PREFIX = 'atbl';\nexport const keyBuilder = createKeyBuilder(STORAGE_KEY_PREFIX, '.');\nexport const STORAGE_KEY_TEST = keyBuilder('check');\n\nexport const PREFIX_SESSION_ID = 'session';\nexport const PREFIX_VISITOR_ID = 'visitor';\n\nconst MINUTE_IN_MS = 1000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_EVENT_QUEUE_SIZE = 1000;\n\nexport const EVENT_PAGEVIEW = '$pageview';\n\nexport const PROPERTY_LIB = '$lib';\nexport const PROPERTY_LIB_VERSION = '$lib_version';\nexport const PROPERTY_REFERER = '$referer';\nexport const PROPERTY_RELEASE = '$release';\nexport const PROPERTY_URL = '$url';\nexport const PROPERTY_VIEWPORT = '$viewport';\n\nexport const TrackingConsent = {\n DENIED: 'denied',\n DISMISSED: 'dismissed',\n GRANTED: 'granted',\n PENDING: 'pending',\n} as const;\n\nexport type TrackingConsentType =\n (typeof TrackingConsent)[keyof typeof TrackingConsent];\n\nexport const RESERVED_USER_IDS = [\n 'anonymous_id',\n 'anonymous',\n 'distinct_id',\n 'distinctid',\n 'false',\n 'guest',\n 'id',\n 'not_authenticated',\n 'true',\n 'undefined',\n 'user_id',\n 'user',\n 'visitor_id',\n 'visitor',\n];\nexport const RESERVED_USER_IDS_CASE_SENSITIVE = new Set([\n '[object Object]',\n '0',\n 'NaN',\n 'none',\n 'None',\n 'null',\n]);\n","import type { EventContext, EventType } from '../types';\n\ntype QueuedEvent<TPayload> = {\n eventType: EventType;\n payload: TPayload;\n sentAt: Date;\n context: EventContext;\n};\n\nexport class EventQueue<TPayload> {\n private _queue: QueuedEvent<TPayload>[] = [];\n private _queueMaxSize: number;\n\n constructor(queueMaxSize: number) {\n this._queueMaxSize = queueMaxSize;\n }\n\n enqueue(\n eventType: 'track' | 'identify',\n payload: TPayload,\n context: EventContext\n ): void {\n if (this._queue.length >= this._queueMaxSize) {\n // Remove oldest event to make room for new one\n this._queue.shift();\n }\n this._queue.push({\n eventType,\n payload,\n context,\n sentAt: new Date(),\n });\n }\n\n flush(): Array<QueuedEvent<TPayload>> {\n const events = [...this._queue];\n this._queue = [];\n return events;\n }\n\n clear(): void {\n this._queue = [];\n }\n\n getSize(): number {\n return this._queue.length;\n }\n}\n","/* eslint-disable no-restricted-globals */\n\n/** Runs code on browser environments safely. */\nexport function safelyRunOnBrowser<TReturn>(\n callback: (params: { window: typeof window }) => TReturn,\n /** Fallback to run on server environments. */\n fallback: () => TReturn = () => undefined as unknown as TReturn\n): TReturn {\n if (typeof window === 'undefined') {\n return fallback();\n }\n\n return callback({ window });\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport function getViewport(): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","/**\n * Throws an error if the condition is not met.\n *\n * The error is exhaustive in development, and becomes generic in production.\n *\n * This is used to make development a better experience to provide guidance as\n * to where the error comes from.\n */\nexport function invariant(\n condition: unknown,\n message: string | (() => string)\n): asserts condition {\n if (condition) {\n return;\n }\n\n if (__DEV__) {\n throw new Error(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n }\n\n throw new Error('Invariant failed');\n}\n","/* eslint-disable no-console */\n\nimport { TrackingConsent, TrackingConsentType } from '../constants';\nimport { EventPayload } from '../types';\n\nexport type Logger = ReturnType<typeof createLogger>;\n\nexport function createLogger(prefix: string) {\n return {\n log: (...args: unknown[]) => {\n console.log(`[${prefix}]`, ...args);\n },\n logHeader: () => {\n const header = `Altertable v${__LIB_VERSION__} %c• Debug mode enabled`;\n const hasAlreadyPrinted = loggerCache.current[header];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[header] = true;\n console.log(header, 'color: #64748b;');\n }\n },\n logEvent: (\n payload: EventPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event\n );\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [timestampLabel, timestampStyle] = createTimestampElement(\n payload.timestamp\n );\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c [${environmentBadgeLabel}] %c(${timestampLabel}) %c${consentBadgeLabel}`,\n eventBadgeStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabelLabel, userLabelStyle] = createLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.user_id ?? 'Not set'\n );\n const [visitorLabelLabel, visitorLabelStyle] =\n createLabelElement('Visitor ID');\n const [visitorValueLabel, visitorValueStyle] = createValueElement(\n payload.visitor_id ?? 'Not set'\n );\n const [sessionLabelLabel, sessionLabelStyle] =\n createLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabelLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${visitorLabelLabel} %c${visitorValueLabel}`,\n visitorLabelStyle,\n visitorValueStyle\n );\n console.log(\n `%c${sessionLabelLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n warn: (...args: unknown[]) => {\n console.warn(`[${prefix}]`, ...args);\n },\n warnDev: (message: string, ...args: unknown[]) => {\n if (!__DEV__) {\n return;\n }\n\n const sanitizedMessage = message.trim();\n const hasAlreadyPrinted = loggerCache.current[sanitizedMessage];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[sanitizedMessage] = true;\n const warning = `[${prefix}] ${sanitizedMessage}`;\n\n console.warn(warning, ...args);\n\n try {\n // Welcome to debugging Altertable.\n //\n // This error was thrown as a convenience so that you can find the source\n // of the warning that appears in the console by enabling \"Pause on exceptions\"\n // in your debugger.\n throw new Error(warning);\n } catch (error) {\n // Do nothing\n }\n }\n },\n error: (...args: unknown[]) => {\n console.error(`[${prefix}]`, ...args);\n },\n };\n}\n\nexport const loggerCache: { current: Record<string, boolean> } = {\n current: {},\n};\n\nfunction formatEventTime(timestamp: string) {\n return new Date(timestamp).toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction createEventBadgeElement(value: string): [string, string] {\n return [\n value,\n 'background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;',\n ];\n}\n\nfunction createEnvironmentBadgeElement(value: string): [string, string] {\n return [value, `color: ${getEnvironmentColor(value)}; font-weight: 400;`];\n}\n\nfunction getEnvironmentColor(environment: string) {\n const formattedEnv = environment.toLocaleLowerCase().startsWith('prod')\n ? 'production'\n : environment;\n\n switch (formattedEnv) {\n case 'production':\n return '#ef4444';\n default:\n return '#3b82f6';\n }\n}\n\nfunction createTimestampElement(value: string): [string, string] {\n return [formatEventTime(value), 'color: #64748b; font-weight: 400;'];\n}\n\nfunction createLabelElement(value: string): [string, string] {\n return [value, 'color: #64748b; font-size: 11px;'];\n}\n\nfunction createValueElement(value: string): [string, string] {\n return [\n value,\n 'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: \"SF Mono\", \"Monaco\", monospace; font-size: 11px;',\n ];\n}\n\nfunction getConsentBadgeElement(\n trackingConsent: TrackingConsentType\n): [string, string] {\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n return ['', ''];\n case TrackingConsent.DENIED:\n return [\n 'DENIED',\n 'background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n return [\n 'PENDING',\n 'background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n default:\n return [\n 'UNKNOWN',\n 'background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n }\n}\n","export function generateId<T extends string>(prefix: T): `${T}-${string}` {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n try {\n return `${prefix}-${crypto.randomUUID()}`;\n } catch {\n // Continue with Math.random() fallback.\n }\n }\n return `${prefix}-${Math.random().toString(36).substring(2)}`;\n}\n","import {\n PREFIX_SESSION_ID,\n PREFIX_VISITOR_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\nimport type { UserId, VisitorId, SessionId } from '../types';\n\ntype SessionData = {\n visitorId: VisitorId;\n sessionId: SessionId;\n userId: UserId | null;\n lastEventAt: string | null;\n trackingConsent: TrackingConsentType;\n};\n\nexport class SessionManager {\n private _defaultTrackingConsent: TrackingConsentType;\n private _logger: Logger;\n private _sessionData: SessionData;\n private _storage: StorageApi;\n private _storageKey: string;\n\n constructor(options: {\n storage: StorageApi;\n storageKey: string;\n logger: Logger;\n defaultTrackingConsent: TrackingConsentType;\n }) {\n this._storage = options.storage;\n this._storageKey = options.storageKey;\n this._logger = options.logger;\n this._defaultTrackingConsent =\n options.defaultTrackingConsent ?? TrackingConsent.PENDING;\n this._sessionData = this._createDefaultSessionData();\n }\n\n init(): void {\n const storedData = this._storage.getItem(this._storageKey);\n\n if (!storedData) {\n this._sessionData = this._createDefaultSessionData();\n this._persistToStorage();\n return;\n }\n\n try {\n const parsedData = JSON.parse(storedData) as Partial<SessionData>;\n\n this._sessionData = {\n visitorId: parsedData.visitorId || this._generateVisitorId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n userId: parsedData.userId || null,\n lastEventAt: parsedData.lastEventAt || null,\n trackingConsent: isValidTrackingConsent(parsedData.trackingConsent)\n ? parsedData.trackingConsent\n : this._defaultTrackingConsent,\n };\n } catch (error) {\n this._logger.warnDev(\n 'Failed to parse storage data. Resetting session data.'\n );\n this._sessionData = this._createDefaultSessionData();\n }\n\n this._persistToStorage();\n }\n\n getVisitorId(): VisitorId {\n return this._sessionData.visitorId;\n }\n\n getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getUserId(): UserId | null {\n return this._sessionData.userId;\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n setUserId(userId: UserId | null): void {\n this._sessionData.userId = userId;\n this._persistToStorage();\n }\n\n setTrackingConsent(consent: TrackingConsentType): void {\n this._sessionData.trackingConsent = consent;\n this._persistToStorage();\n }\n\n updateLastEventAt(timestamp: string): void {\n this._sessionData.lastEventAt = timestamp;\n this._persistToStorage();\n }\n\n renewSessionIfNeeded(): boolean {\n const shouldRenew = this._shouldRenewSession();\n\n if (shouldRenew) {\n this._renewSession();\n this._persistToStorage();\n return true;\n }\n\n return false;\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n resetTrackingConsent = false,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetVisitorId) {\n this._sessionData.visitorId = this._generateVisitorId();\n }\n\n if (resetSessionId) {\n this._sessionData.sessionId = this._generateSessionId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.userId = null;\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n visitorId: this._generateVisitorId(),\n sessionId: this._generateSessionId(),\n userId: null,\n lastEventAt: null,\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateVisitorId(): VisitorId {\n return generateId(PREFIX_VISITOR_ID);\n }\n\n private _shouldRenewSession(): boolean {\n const { lastEventAt } = this._sessionData;\n\n if (!lastEventAt) {\n return true;\n }\n\n const now = new Date().getTime();\n const lastEventTime = new Date(lastEventAt).getTime();\n const timeSinceLastEvent = now - lastEventTime;\n\n return timeSinceLastEvent > SESSION_EXPIRATION_TIME_MS;\n }\n\n private _renewSession(): void {\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.lastEventAt = null;\n }\n\n private _persistToStorage(): void {\n try {\n this._storage.setItem(\n this._storageKey,\n JSON.stringify(this._sessionData)\n );\n } catch (error) {\n this._logger.warnDev('Failed to persist session data to storage.');\n }\n }\n}\n\nfunction isValidTrackingConsent(value: unknown): value is TrackingConsentType {\n return (\n typeof value === 'string' &&\n Object.values(TrackingConsent).includes(value as TrackingConsentType)\n );\n}\n","import { STORAGE_KEY_TEST } from '../constants';\nimport { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport type StorageType =\n | 'localStorage'\n | 'sessionStorage'\n | 'cookie'\n | 'memory'\n | 'localStorage+cookie';\n\nexport interface StorageApi {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n migrate(fromStorage: StorageApi, keys: string[]): void;\n}\n\nfunction migrateKeys(\n toStorage: StorageApi,\n fromStorage: StorageApi,\n keys: string[]\n): void {\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n toStorage.setItem(key, value);\n fromStorage.removeItem(key);\n }\n }\n}\n\nclass MemoryStore implements StorageApi {\n private store: Record<string, string> = {};\n getItem(key: string): string | null {\n return this.store[key] ?? null;\n }\n setItem(key: string, value: string) {\n this.store[key] = value;\n }\n removeItem(key: string) {\n delete this.store[key];\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass CookieStore implements StorageApi {\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n const match = window.document.cookie.match(\n new RegExp('(^| )' + key + '=([^;]+)')\n );\n return match ? decodeURIComponent(match[2]) : null;\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=${encodeURIComponent(value)}; path=/;`;\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=; Max-Age=0; path=/;`;\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass WebStorageStore implements StorageApi {\n constructor(private storage: 'localStorage' | 'sessionStorage') {}\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n try {\n return window[this.storage].getItem(key);\n } catch {\n return null;\n }\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].setItem(key, value);\n } catch {\n /* ignore */\n }\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].removeItem(key);\n } catch {\n /* ignore */\n }\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass LocalPlusCookieStore implements StorageApi {\n private localStore = new WebStorageStore('localStorage');\n private cookieStore = new CookieStore();\n getItem(key: string): string | null {\n return this.localStore.getItem(key) ?? this.cookieStore.getItem(key);\n }\n setItem(key: string, value: string) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n removeItem(key: string) {\n this.localStore.removeItem(key);\n this.cookieStore.removeItem(key);\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n // Migrate to both localStorage and cookie without removing from source yet\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n }\n\n for (const key of keys) {\n fromStorage.removeItem(key);\n }\n }\n}\n\nfunction testStorageSupport(\n storageType: 'localStorage' | 'sessionStorage' | 'cookie'\n) {\n return safelyRunOnBrowser(\n ({ window }) => {\n try {\n if (storageType === 'cookie') {\n window.document.cookie = `${STORAGE_KEY_TEST}=1`;\n const supported =\n window.document.cookie.indexOf(`${STORAGE_KEY_TEST}=`) !== -1;\n window.document.cookie = `${STORAGE_KEY_TEST}=; Max-Age=0`;\n return supported;\n } else {\n window[storageType].setItem(STORAGE_KEY_TEST, '1');\n window[storageType].removeItem(STORAGE_KEY_TEST);\n return true;\n }\n } catch {\n return false;\n }\n },\n () => false\n );\n}\n\nexport function selectStorage(\n type: StorageType | 'unknown',\n params: { onFallback: (message: string) => void }\n): StorageApi {\n const { onFallback } = params;\n\n switch (type) {\n case 'localStorage': {\n if (testStorageSupport('localStorage')) {\n return new WebStorageStore('localStorage');\n }\n onFallback(\n 'localStorage not supported, falling back to localStorage+cookie.'\n );\n return selectStorage('localStorage+cookie', params);\n }\n\n case 'localStorage+cookie': {\n const localStorageSupported = testStorageSupport('localStorage');\n const cookieSupported = testStorageSupport('cookie');\n\n if (localStorageSupported && cookieSupported) {\n return new LocalPlusCookieStore();\n } else if (cookieSupported) {\n onFallback(\n 'localStorage+cookie not fully supported, falling back to cookie.'\n );\n return new CookieStore();\n } else if (localStorageSupported) {\n onFallback('cookie not supported, falling back to localStorage.');\n return new WebStorageStore('localStorage');\n } else {\n onFallback(\n 'Neither localStorage nor cookie supported, falling back to memory.'\n );\n return new MemoryStore();\n }\n }\n\n case 'sessionStorage': {\n if (testStorageSupport('sessionStorage')) {\n return new WebStorageStore('sessionStorage');\n }\n onFallback('sessionStorage not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'cookie': {\n if (testStorageSupport('cookie')) {\n return new CookieStore();\n }\n onFallback('cookie not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'memory': {\n return new MemoryStore();\n }\n\n default: {\n throw new Error(\n `Unknown storage type: \"${type}\". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`\n );\n }\n }\n}\n","import {\n RESERVED_USER_IDS,\n RESERVED_USER_IDS_CASE_SENSITIVE,\n} from '../constants';\n\nconst reservedIdentifiersList = [\n ...RESERVED_USER_IDS,\n ...RESERVED_USER_IDS_CASE_SENSITIVE,\n]\n .map(id => `- \"${id}\"`)\n .join('\\n');\nconst reservedIdentifiersInfo = `List of reserved identifiers:\\n${reservedIdentifiersList}`;\n\nexport function validateUserId(userId: string): void {\n if (!userId || userId.trim() === '') {\n throw new Error('User ID cannot be empty or contain only whitespace.');\n }\n\n const isCaseInsensitiveBlocked = RESERVED_USER_IDS.some(\n blockedId => userId.toLowerCase() === blockedId.toLowerCase()\n );\n\n if (isCaseInsensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n\n const isCaseSensitiveBlocked = RESERVED_USER_IDS_CASE_SENSITIVE.has(userId);\n\n if (isCaseSensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n}\n","import {\n AUTO_CAPTURE_INTERVAL_MS,\n DEFAULT_BASE_URL,\n DEFAULT_ENVIRONMENT,\n DEFAULT_PERSISTENCE,\n EVENT_PAGEVIEW,\n keyBuilder,\n MAX_EVENT_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { EventQueue } from './lib/eventQueue';\nimport { getViewport } from './lib/getViewport';\nimport { invariant } from './lib/invariant';\nimport { createLogger } from './lib/logger';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\nimport { SessionManager } from './lib/sessionManager';\nimport {\n selectStorage,\n type StorageApi,\n type StorageType,\n} from './lib/storage';\nimport { validateUserId } from './lib/validateUserId';\nimport {\n EventContext,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n UserTraits,\n} from './types';\n\nexport interface AltertableConfig {\n /**\n * The base URL of the Altertable API.\n * @default https://api.altertable.ai\n */\n baseUrl?: string;\n /**\n * The environment of the application.\n * @default \"production\"\n */\n environment?: string;\n /**\n * Whether to automatically capture page views and events.\n * @default true\n */\n autoCapture?: boolean;\n /**\n * The release ID of the application.\n * This is helpful to identify the version of the application an event is coming from.\n */\n release?: string;\n /**\n * Whether to log events to the console.\n * @default false\n */\n debug?: boolean;\n /**\n * The persistence strategy for storing IDs.\n * @default \"localStorage+cookie\"\n */\n persistence?: StorageType;\n /**\n * The tracking consent state.\n * @default \"pending\"\n */\n trackingConsent?: TrackingConsentType;\n}\n\nexport class Altertable {\n private _apiKey: string;\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _eventQueue: EventQueue<EventPayload | IdentifyPayload>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _sessionManager: SessionManager | undefined;\n private _storage: StorageApi | undefined;\n private _storageKey: string | undefined;\n\n constructor() {\n this._lastUrl = null;\n this._referrer = null;\n this._eventQueue = new EventQueue(MAX_EVENT_QUEUE_SIZE);\n }\n\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._apiKey = apiKey;\n this._config = config;\n this._storageKey = keyBuilder(\n apiKey,\n this._config.environment || DEFAULT_ENVIRONMENT\n );\n this._referrer = safelyRunOnBrowser<string | null>(\n ({ window }) => window.document.referrer || null,\n () => null\n );\n this._lastUrl = safelyRunOnBrowser<string | null>(\n ({ window }) => window.location.href || null,\n () => null\n );\n const persistence: StorageType = config.persistence ?? DEFAULT_PERSISTENCE;\n this._storage = selectStorage(persistence, {\n onFallback: message => this._logger.warn(message),\n });\n\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: config.trackingConsent ?? TrackingConsent.PENDING,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n this._handleAutoCaptureChange(config.autoCapture ?? true);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n configure(updates: Partial<AltertableConfig>) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before configuring.'\n );\n\n if (\n updates.autoCapture !== undefined &&\n updates.autoCapture !== this._config.autoCapture\n ) {\n this._handleAutoCaptureChange(updates.autoCapture);\n }\n\n if (\n updates.persistence !== undefined &&\n updates.persistence !== this._config.persistence\n ) {\n const previousStorage = this._storage;\n this._storage = selectStorage(updates.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._storage.migrate(previousStorage, [this._storageKey]);\n }\n\n const currentTrackingConsent = this._sessionManager.getTrackingConsent();\n if (\n updates.trackingConsent !== undefined &&\n updates.trackingConsent !== currentTrackingConsent\n ) {\n this._sessionManager.setTrackingConsent(updates.trackingConsent);\n\n if (\n currentTrackingConsent !== TrackingConsent.GRANTED &&\n updates.trackingConsent === TrackingConsent.GRANTED\n ) {\n const queuedEvents = this._eventQueue.flush();\n if (queuedEvents.length > 0) {\n queuedEvents.forEach(event => {\n this._processEvent(event.eventType, event.payload, event.context);\n });\n }\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._eventQueue.clear();\n }\n }\n\n this._config = { ...this._config, ...updates };\n }\n\n private _handleAutoCaptureChange(enableAutoCapture: boolean) {\n this._cleanupAutoCapture?.();\n\n if (enableAutoCapture) {\n if (this._lastUrl) {\n this.page(this._lastUrl);\n }\n\n const checkForChanges = this._checkForChanges.bind(this);\n const intervalId = setInterval(checkForChanges, AUTO_CAPTURE_INTERVAL_MS);\n\n safelyRunOnBrowser(({ window }) => {\n window.addEventListener('popstate', checkForChanges);\n window.addEventListener('hashchange', checkForChanges);\n });\n\n this._cleanupAutoCapture = () => {\n clearInterval(intervalId);\n safelyRunOnBrowser(({ window }) => {\n window.removeEventListener('popstate', checkForChanges);\n window.removeEventListener('hashchange', checkForChanges);\n });\n };\n } else {\n this._cleanupAutoCapture = undefined;\n }\n }\n\n identify(userId: string, traits: UserTraits = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before identifying users.'\n );\n\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n this._sessionManager.setUserId(userId);\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n updateTraits(traits: UserTraits) {\n const userId = this._sessionManager.getUserId();\n invariant(\n userId,\n 'User must be identified with identify() before updating traits.'\n );\n\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n } = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before resetting.'\n );\n\n this._sessionManager.reset({ resetVisitorId, resetSessionId });\n }\n\n page(url: string) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking page views.'\n );\n\n const parsedUrl = new URL(url);\n const urlWithoutSearch = `${parsedUrl.origin}${parsedUrl.pathname}`;\n this.track(EVENT_PAGEVIEW, {\n [PROPERTY_URL]: urlWithoutSearch,\n [PROPERTY_VIEWPORT]: getViewport(),\n [PROPERTY_REFERER]: this._referrer,\n ...Object.fromEntries(parsedUrl.searchParams),\n });\n }\n\n track(event: string, properties: EventProperties = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking events.'\n );\n\n this._sessionManager.renewSessionIfNeeded();\n const timestamp = new Date().toISOString();\n this._sessionManager.updateLastEventAt(timestamp);\n\n const context = this._getEventContext();\n const payload: EventPayload = {\n timestamp,\n event,\n environment: context.environment,\n user_id: context.user_id,\n session_id: context.session_id,\n visitor_id: context.visitor_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...properties,\n },\n };\n\n this._processEvent('track', payload, context);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionManager.getTrackingConsent();\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n if (!this._config.autoCapture) {\n return;\n }\n\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this.page(currentUrl);\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n }\n });\n }\n\n private _getEventContext(): EventContext {\n return {\n environment: this._config.environment || DEFAULT_ENVIRONMENT,\n user_id: this._sessionManager.getUserId(),\n visitor_id: this._sessionManager.getVisitorId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload | IdentifyPayload>(\n eventType: EventType,\n payload: TPayload,\n context: EventContext\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._request(`/${eventType}`, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._eventQueue.enqueue(eventType, payload, context);\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private _request(path: string, body: unknown): void {\n invariant(this._apiKey, 'Missing API key');\n invariant(this._config, 'Missing configuration');\n\n const url = `${this._config.baseUrl || DEFAULT_BASE_URL}${path}`;\n const payload = JSON.stringify(body);\n\n /* eslint-disable no-restricted-globals */\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n const beaconUrl = `${url}?apiKey=${encodeURIComponent(this._apiKey)}`;\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(beaconUrl, blob);\n } /* eslint-enable no-restricted-globals */ else {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._apiKey}`,\n },\n body: payload,\n });\n }\n }\n}\n"],"mappings":"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","names":["index_exports","__export","TrackingConsent","altertable","__toCommonJS","createKeyBuilder","prefix","separator","parts","DEFAULT_BASE_URL","DEFAULT_ENVIRONMENT","DEFAULT_PERSISTENCE","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_EVENT_QUEUE_SIZE","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","EventQueue","queueMaxSize","eventType","payload","context","events","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","invariant","condition","message","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabelLabel","userLabelStyle","createLabelElement","userValueLabel","userValueStyle","createValueElement","visitorLabelLabel","visitorLabelStyle","visitorValueLabel","visitorValueStyle","sessionLabelLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","value","getEnvironmentColor","environment","TrackingConsent","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetVisitorId","resetSessionId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","lastEventAt","now","lastEventTime","SESSION_EXPIRATION_TIME_MS","value","migrateKeys","toStorage","fromStorage","keys","key","value","MemoryStore","CookieStore","safelyRunOnBrowser","window","match","WebStorageStore","storage","LocalPlusCookieStore","testStorageSupport","storageType","STORAGE_KEY_TEST","supported","selectStorage","type","params","onFallback","localStorageSupported","cookieSupported","reservedIdentifiersList","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","id","reservedIdentifiersInfo","validateUserId","userId","blockedId","Altertable","createLogger","EventQueue","MAX_EVENT_QUEUE_SIZE","apiKey","config","invariant","keyBuilder","DEFAULT_ENVIRONMENT","safelyRunOnBrowser","window","persistence","DEFAULT_PERSISTENCE","selectStorage","message","SessionManager","TrackingConsent","updates","previousStorage","currentTrackingConsent","queuedEvents","event","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","resetVisitorId","resetSessionId","url","parsedUrl","urlWithoutSearch","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","getViewport","PROPERTY_REFERER","properties","timestamp","payload","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","trackingConsent","currentUrl","eventType","path","body","DEFAULT_BASE_URL","beaconUrl","blob","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/createKeyBuilder.ts","../src/constants.ts","../src/lib/eventQueue.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/getViewport.ts","../src/lib/invariant.ts","../src/lib/logger.ts","../src/lib/generateId.ts","../src/lib/sessionManager.ts","../src/lib/storage.ts","../src/lib/validateUserId.ts","../src/core.ts"],"sourcesContent":["import { TrackingConsent } from './constants';\nimport { Altertable, type AltertableConfig } from './core';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\n\nexport type { Altertable, AltertableConfig };\nexport { TrackingConsent };\n\ndeclare global {\n interface Window {\n Altertable: Altertable | Array<Array<unknown>> | undefined;\n }\n}\n\nexport const altertable = new Altertable();\n\nsafelyRunOnBrowser(({ window }) => {\n const stub = window.Altertable;\n if (stub && Array.isArray(stub)) {\n for (const item of stub) {\n const method = item[0];\n const args = item.slice(1);\n (altertable[method as keyof Altertable] as any)(...args);\n }\n }\n\n window.Altertable = altertable;\n});\n","export function createKeyBuilder(prefix: string, separator: string) {\n return (...parts: string[]) => {\n return [prefix, ...parts].join(separator);\n };\n}\n","import { createKeyBuilder } from './lib/createKeyBuilder';\n\nexport const DEFAULT_BASE_URL = 'https://api.altertable.ai';\nexport const DEFAULT_ENVIRONMENT = 'production';\nexport const DEFAULT_PERSISTENCE = 'localStorage+cookie';\n\nconst STORAGE_KEY_PREFIX = 'atbl';\nexport const keyBuilder = createKeyBuilder(STORAGE_KEY_PREFIX, '.');\nexport const STORAGE_KEY_TEST = keyBuilder('check');\n\nexport const PREFIX_SESSION_ID = 'session';\nexport const PREFIX_VISITOR_ID = 'visitor';\n\nconst MINUTE_IN_MS = 1000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_EVENT_QUEUE_SIZE = 1000;\n\nexport const EVENT_PAGEVIEW = '$pageview';\n\nexport const PROPERTY_LIB = '$lib';\nexport const PROPERTY_LIB_VERSION = '$lib_version';\nexport const PROPERTY_REFERER = '$referer';\nexport const PROPERTY_RELEASE = '$release';\nexport const PROPERTY_URL = '$url';\nexport const PROPERTY_VIEWPORT = '$viewport';\n\nexport const TrackingConsent = {\n DENIED: 'denied',\n DISMISSED: 'dismissed',\n GRANTED: 'granted',\n PENDING: 'pending',\n} as const;\n\nexport type TrackingConsentType =\n (typeof TrackingConsent)[keyof typeof TrackingConsent];\n\nexport const RESERVED_USER_IDS = [\n 'anonymous_id',\n 'anonymous',\n 'distinct_id',\n 'distinctid',\n 'false',\n 'guest',\n 'id',\n 'not_authenticated',\n 'true',\n 'undefined',\n 'user_id',\n 'user',\n 'visitor_id',\n 'visitor',\n];\nexport const RESERVED_USER_IDS_CASE_SENSITIVE = new Set([\n '[object Object]',\n '0',\n 'NaN',\n 'none',\n 'None',\n 'null',\n]);\n","import type { EventContext, EventType } from '../types';\n\ntype QueuedEvent<TPayload> = {\n eventType: EventType;\n payload: TPayload;\n sentAt: Date;\n context: EventContext;\n};\n\nexport class EventQueue<TPayload> {\n private _queue: QueuedEvent<TPayload>[] = [];\n private _queueMaxSize: number;\n\n constructor(queueMaxSize: number) {\n this._queueMaxSize = queueMaxSize;\n }\n\n enqueue(\n eventType: 'track' | 'identify',\n payload: TPayload,\n context: EventContext\n ): void {\n if (this._queue.length >= this._queueMaxSize) {\n // Remove oldest event to make room for new one\n this._queue.shift();\n }\n this._queue.push({\n eventType,\n payload,\n context,\n sentAt: new Date(),\n });\n }\n\n flush(): Array<QueuedEvent<TPayload>> {\n const events = [...this._queue];\n this._queue = [];\n return events;\n }\n\n clear(): void {\n this._queue = [];\n }\n\n getSize(): number {\n return this._queue.length;\n }\n}\n","/* eslint-disable no-restricted-globals */\n\n/** Runs code on browser environments safely. */\nexport function safelyRunOnBrowser<TReturn>(\n callback: (params: { window: typeof window }) => TReturn,\n /** Fallback to run on server environments. */\n fallback: () => TReturn = () => undefined as unknown as TReturn\n): TReturn {\n if (typeof window === 'undefined') {\n return fallback();\n }\n\n return callback({ window });\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport function getViewport(): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","/**\n * Throws an error if the condition is not met.\n *\n * The error is exhaustive in development, and becomes generic in production.\n *\n * This is used to make development a better experience to provide guidance as\n * to where the error comes from.\n */\nexport function invariant(\n condition: unknown,\n message: string | (() => string)\n): asserts condition {\n if (condition) {\n return;\n }\n\n if (__DEV__) {\n throw new Error(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n }\n\n throw new Error('Invariant failed');\n}\n","/* eslint-disable no-console */\n\nimport { TrackingConsent, TrackingConsentType } from '../constants';\nimport { EventPayload } from '../types';\n\nexport type Logger = ReturnType<typeof createLogger>;\n\nexport function createLogger(prefix: string) {\n return {\n log: (...args: unknown[]) => {\n console.log(`[${prefix}]`, ...args);\n },\n logHeader: () => {\n const header = `Altertable v${__LIB_VERSION__} %c• Debug mode enabled`;\n const hasAlreadyPrinted = loggerCache.current[header];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[header] = true;\n console.log(header, 'color: #64748b;');\n }\n },\n logEvent: (\n payload: EventPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event\n );\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [timestampLabel, timestampStyle] = createTimestampElement(\n payload.timestamp\n );\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c [${environmentBadgeLabel}] %c(${timestampLabel}) %c${consentBadgeLabel}`,\n eventBadgeStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabelLabel, userLabelStyle] = createLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.user_id ?? 'Not set'\n );\n const [visitorLabelLabel, visitorLabelStyle] =\n createLabelElement('Visitor ID');\n const [visitorValueLabel, visitorValueStyle] = createValueElement(\n payload.visitor_id ?? 'Not set'\n );\n const [sessionLabelLabel, sessionLabelStyle] =\n createLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabelLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${visitorLabelLabel} %c${visitorValueLabel}`,\n visitorLabelStyle,\n visitorValueStyle\n );\n console.log(\n `%c${sessionLabelLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n warn: (...args: unknown[]) => {\n console.warn(`[${prefix}]`, ...args);\n },\n warnDev: (message: string, ...args: unknown[]) => {\n if (!__DEV__) {\n return;\n }\n\n const sanitizedMessage = message.trim();\n const hasAlreadyPrinted = loggerCache.current[sanitizedMessage];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[sanitizedMessage] = true;\n const warning = `[${prefix}] ${sanitizedMessage}`;\n\n console.warn(warning, ...args);\n\n try {\n // Welcome to debugging Altertable.\n //\n // This error was thrown as a convenience so that you can find the source\n // of the warning that appears in the console by enabling \"Pause on exceptions\"\n // in your debugger.\n throw new Error(warning);\n } catch (error) {\n // Do nothing\n }\n }\n },\n error: (...args: unknown[]) => {\n console.error(`[${prefix}]`, ...args);\n },\n };\n}\n\nexport const loggerCache: { current: Record<string, boolean> } = {\n current: {},\n};\n\nfunction formatEventTime(timestamp: string) {\n return new Date(timestamp).toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction createEventBadgeElement(value: string): [string, string] {\n return [\n value,\n 'background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;',\n ];\n}\n\nfunction createEnvironmentBadgeElement(value: string): [string, string] {\n return [value, `color: ${getEnvironmentColor(value)}; font-weight: 400;`];\n}\n\nfunction getEnvironmentColor(environment: string) {\n const formattedEnv = environment.toLocaleLowerCase().startsWith('prod')\n ? 'production'\n : environment;\n\n switch (formattedEnv) {\n case 'production':\n return '#ef4444';\n default:\n return '#3b82f6';\n }\n}\n\nfunction createTimestampElement(value: string): [string, string] {\n return [formatEventTime(value), 'color: #64748b; font-weight: 400;'];\n}\n\nfunction createLabelElement(value: string): [string, string] {\n return [value, 'color: #64748b; font-size: 11px;'];\n}\n\nfunction createValueElement(value: string): [string, string] {\n return [\n value,\n 'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: \"SF Mono\", \"Monaco\", monospace; font-size: 11px;',\n ];\n}\n\nfunction getConsentBadgeElement(\n trackingConsent: TrackingConsentType\n): [string, string] {\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n return ['', ''];\n case TrackingConsent.DENIED:\n return [\n 'DENIED',\n 'background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n return [\n 'PENDING',\n 'background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n default:\n return [\n 'UNKNOWN',\n 'background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n }\n}\n","export function generateId<T extends string>(prefix: T): `${T}-${string}` {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n try {\n return `${prefix}-${crypto.randomUUID()}`;\n } catch {\n // Continue with Math.random() fallback.\n }\n }\n return `${prefix}-${Math.random().toString(36).substring(2)}`;\n}\n","import {\n PREFIX_SESSION_ID,\n PREFIX_VISITOR_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\nimport type { UserId, VisitorId, SessionId } from '../types';\n\ntype SessionData = {\n visitorId: VisitorId;\n sessionId: SessionId;\n userId: UserId | null;\n lastEventAt: string | null;\n trackingConsent: TrackingConsentType;\n};\n\nexport class SessionManager {\n private _defaultTrackingConsent: TrackingConsentType;\n private _logger: Logger;\n private _sessionData: SessionData;\n private _storage: StorageApi;\n private _storageKey: string;\n\n constructor(options: {\n storage: StorageApi;\n storageKey: string;\n logger: Logger;\n defaultTrackingConsent: TrackingConsentType;\n }) {\n this._storage = options.storage;\n this._storageKey = options.storageKey;\n this._logger = options.logger;\n this._defaultTrackingConsent =\n options.defaultTrackingConsent ?? TrackingConsent.PENDING;\n this._sessionData = this._createDefaultSessionData();\n }\n\n init(): void {\n const storedData = this._storage.getItem(this._storageKey);\n\n if (!storedData) {\n this._sessionData = this._createDefaultSessionData();\n this._persistToStorage();\n return;\n }\n\n try {\n const parsedData = JSON.parse(storedData) as Partial<SessionData>;\n\n this._sessionData = {\n visitorId: parsedData.visitorId || this._generateVisitorId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n userId: parsedData.userId || null,\n lastEventAt: parsedData.lastEventAt || null,\n trackingConsent: isValidTrackingConsent(parsedData.trackingConsent)\n ? parsedData.trackingConsent\n : this._defaultTrackingConsent,\n };\n } catch (error) {\n this._logger.warnDev(\n 'Failed to parse storage data. Resetting session data.'\n );\n this._sessionData = this._createDefaultSessionData();\n }\n\n this._persistToStorage();\n }\n\n getVisitorId(): VisitorId {\n return this._sessionData.visitorId;\n }\n\n getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getUserId(): UserId | null {\n return this._sessionData.userId;\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n setUserId(userId: UserId | null): void {\n this._sessionData.userId = userId;\n this._persistToStorage();\n }\n\n setTrackingConsent(consent: TrackingConsentType): void {\n this._sessionData.trackingConsent = consent;\n this._persistToStorage();\n }\n\n updateLastEventAt(timestamp: string): void {\n this._sessionData.lastEventAt = timestamp;\n this._persistToStorage();\n }\n\n renewSessionIfNeeded(): boolean {\n const shouldRenew = this._shouldRenewSession();\n\n if (shouldRenew) {\n this._renewSession();\n this._persistToStorage();\n return true;\n }\n\n return false;\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n resetTrackingConsent = false,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetVisitorId) {\n this._sessionData.visitorId = this._generateVisitorId();\n }\n\n if (resetSessionId) {\n this._sessionData.sessionId = this._generateSessionId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.userId = null;\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n visitorId: this._generateVisitorId(),\n sessionId: this._generateSessionId(),\n userId: null,\n lastEventAt: null,\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateVisitorId(): VisitorId {\n return generateId(PREFIX_VISITOR_ID);\n }\n\n private _shouldRenewSession(): boolean {\n const { lastEventAt } = this._sessionData;\n\n if (!lastEventAt) {\n return true;\n }\n\n const now = new Date().getTime();\n const lastEventTime = new Date(lastEventAt).getTime();\n const timeSinceLastEvent = now - lastEventTime;\n\n return timeSinceLastEvent > SESSION_EXPIRATION_TIME_MS;\n }\n\n private _renewSession(): void {\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.lastEventAt = null;\n }\n\n private _persistToStorage(): void {\n try {\n this._storage.setItem(\n this._storageKey,\n JSON.stringify(this._sessionData)\n );\n } catch (error) {\n this._logger.warnDev('Failed to persist session data to storage.');\n }\n }\n}\n\nfunction isValidTrackingConsent(value: unknown): value is TrackingConsentType {\n return (\n typeof value === 'string' &&\n Object.values(TrackingConsent).includes(value as TrackingConsentType)\n );\n}\n","import { STORAGE_KEY_TEST } from '../constants';\nimport { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport type StorageType =\n | 'localStorage'\n | 'sessionStorage'\n | 'cookie'\n | 'memory'\n | 'localStorage+cookie';\n\nexport interface StorageApi {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n migrate(fromStorage: StorageApi, keys: string[]): void;\n}\n\nfunction migrateKeys(\n toStorage: StorageApi,\n fromStorage: StorageApi,\n keys: string[]\n): void {\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n toStorage.setItem(key, value);\n fromStorage.removeItem(key);\n }\n }\n}\n\nclass MemoryStore implements StorageApi {\n private store: Record<string, string> = {};\n getItem(key: string): string | null {\n return this.store[key] ?? null;\n }\n setItem(key: string, value: string) {\n this.store[key] = value;\n }\n removeItem(key: string) {\n delete this.store[key];\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass CookieStore implements StorageApi {\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n const match = window.document.cookie.match(\n new RegExp('(^| )' + key + '=([^;]+)')\n );\n return match ? decodeURIComponent(match[2]) : null;\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=${encodeURIComponent(value)}; path=/;`;\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=; Max-Age=0; path=/;`;\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass WebStorageStore implements StorageApi {\n constructor(private storage: 'localStorage' | 'sessionStorage') {}\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n try {\n return window[this.storage].getItem(key);\n } catch {\n return null;\n }\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].setItem(key, value);\n } catch {\n /* ignore */\n }\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].removeItem(key);\n } catch {\n /* ignore */\n }\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass LocalPlusCookieStore implements StorageApi {\n private localStore = new WebStorageStore('localStorage');\n private cookieStore = new CookieStore();\n getItem(key: string): string | null {\n return this.localStore.getItem(key) ?? this.cookieStore.getItem(key);\n }\n setItem(key: string, value: string) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n removeItem(key: string) {\n this.localStore.removeItem(key);\n this.cookieStore.removeItem(key);\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n // Migrate to both localStorage and cookie without removing from source yet\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n }\n\n for (const key of keys) {\n fromStorage.removeItem(key);\n }\n }\n}\n\nfunction testStorageSupport(\n storageType: 'localStorage' | 'sessionStorage' | 'cookie'\n) {\n return safelyRunOnBrowser(\n ({ window }) => {\n try {\n if (storageType === 'cookie') {\n window.document.cookie = `${STORAGE_KEY_TEST}=1`;\n const supported =\n window.document.cookie.indexOf(`${STORAGE_KEY_TEST}=`) !== -1;\n window.document.cookie = `${STORAGE_KEY_TEST}=; Max-Age=0`;\n return supported;\n } else {\n window[storageType].setItem(STORAGE_KEY_TEST, '1');\n window[storageType].removeItem(STORAGE_KEY_TEST);\n return true;\n }\n } catch {\n return false;\n }\n },\n () => false\n );\n}\n\nexport function selectStorage(\n type: StorageType | 'unknown',\n params: { onFallback: (message: string) => void }\n): StorageApi {\n const { onFallback } = params;\n\n switch (type) {\n case 'localStorage': {\n if (testStorageSupport('localStorage')) {\n return new WebStorageStore('localStorage');\n }\n onFallback(\n 'localStorage not supported, falling back to localStorage+cookie.'\n );\n return selectStorage('localStorage+cookie', params);\n }\n\n case 'localStorage+cookie': {\n const localStorageSupported = testStorageSupport('localStorage');\n const cookieSupported = testStorageSupport('cookie');\n\n if (localStorageSupported && cookieSupported) {\n return new LocalPlusCookieStore();\n } else if (cookieSupported) {\n onFallback(\n 'localStorage+cookie not fully supported, falling back to cookie.'\n );\n return new CookieStore();\n } else if (localStorageSupported) {\n onFallback('cookie not supported, falling back to localStorage.');\n return new WebStorageStore('localStorage');\n } else {\n onFallback(\n 'Neither localStorage nor cookie supported, falling back to memory.'\n );\n return new MemoryStore();\n }\n }\n\n case 'sessionStorage': {\n if (testStorageSupport('sessionStorage')) {\n return new WebStorageStore('sessionStorage');\n }\n onFallback('sessionStorage not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'cookie': {\n if (testStorageSupport('cookie')) {\n return new CookieStore();\n }\n onFallback('cookie not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'memory': {\n return new MemoryStore();\n }\n\n default: {\n throw new Error(\n `Unknown storage type: \"${type}\". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`\n );\n }\n }\n}\n","import {\n RESERVED_USER_IDS,\n RESERVED_USER_IDS_CASE_SENSITIVE,\n} from '../constants';\n\nconst reservedIdentifiersList = [\n ...RESERVED_USER_IDS,\n ...RESERVED_USER_IDS_CASE_SENSITIVE,\n]\n .map(id => `- \"${id}\"`)\n .join('\\n');\nconst reservedIdentifiersInfo = `List of reserved identifiers:\\n${reservedIdentifiersList}`;\n\nexport function validateUserId(userId: string): void {\n if (!userId || userId.trim() === '') {\n throw new Error('User ID cannot be empty or contain only whitespace.');\n }\n\n const isCaseInsensitiveBlocked = RESERVED_USER_IDS.some(\n blockedId => userId.toLowerCase() === blockedId.toLowerCase()\n );\n\n if (isCaseInsensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n\n const isCaseSensitiveBlocked = RESERVED_USER_IDS_CASE_SENSITIVE.has(userId);\n\n if (isCaseSensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n}\n","import {\n AUTO_CAPTURE_INTERVAL_MS,\n DEFAULT_BASE_URL,\n DEFAULT_ENVIRONMENT,\n DEFAULT_PERSISTENCE,\n EVENT_PAGEVIEW,\n keyBuilder,\n MAX_EVENT_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { EventQueue } from './lib/eventQueue';\nimport { getViewport } from './lib/getViewport';\nimport { invariant } from './lib/invariant';\nimport { createLogger } from './lib/logger';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\nimport { SessionManager } from './lib/sessionManager';\nimport {\n selectStorage,\n type StorageApi,\n type StorageType,\n} from './lib/storage';\nimport { validateUserId } from './lib/validateUserId';\nimport {\n EventContext,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n UserTraits,\n} from './types';\n\nexport interface AltertableConfig {\n /**\n * The base URL of the Altertable API.\n * @default https://api.altertable.ai\n */\n baseUrl?: string;\n /**\n * The environment of the application.\n * @default \"production\"\n */\n environment?: string;\n /**\n * Whether to automatically capture page views and events.\n * @default true\n */\n autoCapture?: boolean;\n /**\n * The release ID of the application.\n * This is helpful to identify the version of the application an event is coming from.\n */\n release?: string;\n /**\n * Whether to log events to the console.\n * @default false\n */\n debug?: boolean;\n /**\n * The persistence strategy for storing IDs.\n * @default \"localStorage+cookie\"\n */\n persistence?: StorageType;\n /**\n * The tracking consent state.\n * @default \"pending\"\n */\n trackingConsent?: TrackingConsentType;\n}\n\nexport class Altertable {\n private _apiKey: string;\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _eventQueue: EventQueue<EventPayload | IdentifyPayload>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _sessionManager: SessionManager | undefined;\n private _storage: StorageApi | undefined;\n private _storageKey: string | undefined;\n\n constructor() {\n this._lastUrl = null;\n this._referrer = null;\n this._eventQueue = new EventQueue(MAX_EVENT_QUEUE_SIZE);\n }\n\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._apiKey = apiKey;\n this._config = config;\n this._storageKey = keyBuilder(\n apiKey,\n this._config.environment || DEFAULT_ENVIRONMENT\n );\n this._referrer = safelyRunOnBrowser<string | null>(\n ({ window }) => window.document.referrer || null,\n () => null\n );\n this._lastUrl = safelyRunOnBrowser<string | null>(\n ({ window }) => window.location.href || null,\n () => null\n );\n const persistence: StorageType = config.persistence ?? DEFAULT_PERSISTENCE;\n this._storage = selectStorage(persistence, {\n onFallback: message => this._logger.warn(message),\n });\n\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: config.trackingConsent ?? TrackingConsent.PENDING,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n this._handleAutoCaptureChange(config.autoCapture ?? true);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n configure(updates: Partial<AltertableConfig>) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before configuring.'\n );\n\n if (\n updates.autoCapture !== undefined &&\n updates.autoCapture !== this._config.autoCapture\n ) {\n this._handleAutoCaptureChange(updates.autoCapture);\n }\n\n if (\n updates.persistence !== undefined &&\n updates.persistence !== this._config.persistence\n ) {\n const previousStorage = this._storage;\n this._storage = selectStorage(updates.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._storage.migrate(previousStorage, [this._storageKey]);\n }\n\n const currentTrackingConsent = this._sessionManager.getTrackingConsent();\n if (\n updates.trackingConsent !== undefined &&\n updates.trackingConsent !== currentTrackingConsent\n ) {\n this._sessionManager.setTrackingConsent(updates.trackingConsent);\n\n if (\n currentTrackingConsent !== TrackingConsent.GRANTED &&\n updates.trackingConsent === TrackingConsent.GRANTED\n ) {\n const queuedEvents = this._eventQueue.flush();\n if (queuedEvents.length > 0) {\n queuedEvents.forEach(event => {\n this._processEvent(event.eventType, event.payload, event.context);\n });\n }\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._eventQueue.clear();\n }\n }\n\n this._config = { ...this._config, ...updates };\n }\n\n private _handleAutoCaptureChange(enableAutoCapture: boolean) {\n this._cleanupAutoCapture?.();\n\n if (enableAutoCapture) {\n if (this._lastUrl) {\n this.page(this._lastUrl);\n }\n\n const checkForChanges = this._checkForChanges.bind(this);\n const intervalId = setInterval(checkForChanges, AUTO_CAPTURE_INTERVAL_MS);\n\n safelyRunOnBrowser(({ window }) => {\n window.addEventListener('popstate', checkForChanges);\n window.addEventListener('hashchange', checkForChanges);\n });\n\n this._cleanupAutoCapture = () => {\n clearInterval(intervalId);\n safelyRunOnBrowser(({ window }) => {\n window.removeEventListener('popstate', checkForChanges);\n window.removeEventListener('hashchange', checkForChanges);\n });\n };\n } else {\n this._cleanupAutoCapture = undefined;\n }\n }\n\n identify(userId: string, traits: UserTraits = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before identifying users.'\n );\n\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n this._sessionManager.setUserId(userId);\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n updateTraits(traits: UserTraits) {\n const userId = this._sessionManager.getUserId();\n invariant(\n userId,\n 'User must be identified with identify() before updating traits.'\n );\n\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n } = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before resetting.'\n );\n\n this._sessionManager.reset({ resetVisitorId, resetSessionId });\n }\n\n page(url: string) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking page views.'\n );\n\n const parsedUrl = new URL(url);\n const urlWithoutSearch = `${parsedUrl.origin}${parsedUrl.pathname}`;\n this.track(EVENT_PAGEVIEW, {\n [PROPERTY_URL]: urlWithoutSearch,\n [PROPERTY_VIEWPORT]: getViewport(),\n [PROPERTY_REFERER]: this._referrer,\n ...Object.fromEntries(parsedUrl.searchParams),\n });\n }\n\n track(event: string, properties: EventProperties = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking events.'\n );\n\n this._sessionManager.renewSessionIfNeeded();\n const timestamp = new Date().toISOString();\n this._sessionManager.updateLastEventAt(timestamp);\n\n const context = this._getEventContext();\n const payload: EventPayload = {\n timestamp,\n event,\n environment: context.environment,\n user_id: context.user_id,\n session_id: context.session_id,\n visitor_id: context.visitor_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...properties,\n },\n };\n\n this._processEvent('track', payload, context);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionManager.getTrackingConsent();\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this.page(currentUrl);\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n }\n });\n }\n\n private _getEventContext(): EventContext {\n return {\n environment: this._config.environment || DEFAULT_ENVIRONMENT,\n user_id: this._sessionManager.getUserId(),\n visitor_id: this._sessionManager.getVisitorId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload | IdentifyPayload>(\n eventType: EventType,\n payload: TPayload,\n context: EventContext\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._request(`/${eventType}`, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._eventQueue.enqueue(eventType, payload, context);\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private _request(path: string, body: unknown): void {\n invariant(this._apiKey, 'Missing API key');\n invariant(this._config, 'Missing configuration');\n\n const url = `${this._config.baseUrl || DEFAULT_BASE_URL}${path}`;\n const payload = JSON.stringify(body);\n\n /* eslint-disable no-restricted-globals */\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n const beaconUrl = `${url}?apiKey=${encodeURIComponent(this._apiKey)}`;\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(beaconUrl, blob);\n } /* eslint-enable no-restricted-globals */ else {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._apiKey}`,\n },\n body: payload,\n });\n }\n }\n}\n"],"mappings":"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","names":["index_exports","__export","TrackingConsent","altertable","__toCommonJS","createKeyBuilder","prefix","separator","parts","DEFAULT_BASE_URL","DEFAULT_ENVIRONMENT","DEFAULT_PERSISTENCE","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_EVENT_QUEUE_SIZE","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","EventQueue","queueMaxSize","eventType","payload","context","events","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","invariant","condition","message","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabelLabel","userLabelStyle","createLabelElement","userValueLabel","userValueStyle","createValueElement","visitorLabelLabel","visitorLabelStyle","visitorValueLabel","visitorValueStyle","sessionLabelLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","value","getEnvironmentColor","environment","TrackingConsent","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetVisitorId","resetSessionId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","lastEventAt","now","lastEventTime","SESSION_EXPIRATION_TIME_MS","value","migrateKeys","toStorage","fromStorage","keys","key","value","MemoryStore","CookieStore","safelyRunOnBrowser","window","match","WebStorageStore","storage","LocalPlusCookieStore","testStorageSupport","storageType","STORAGE_KEY_TEST","supported","selectStorage","type","params","onFallback","localStorageSupported","cookieSupported","reservedIdentifiersList","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","id","reservedIdentifiersInfo","validateUserId","userId","blockedId","Altertable","createLogger","EventQueue","MAX_EVENT_QUEUE_SIZE","apiKey","config","invariant","keyBuilder","DEFAULT_ENVIRONMENT","safelyRunOnBrowser","window","persistence","DEFAULT_PERSISTENCE","selectStorage","message","SessionManager","TrackingConsent","updates","previousStorage","currentTrackingConsent","queuedEvents","event","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","resetVisitorId","resetSessionId","url","parsedUrl","urlWithoutSearch","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","getViewport","PROPERTY_REFERER","properties","timestamp","payload","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","trackingConsent","currentUrl","eventType","path","body","DEFAULT_BASE_URL","beaconUrl","blob","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- /*! @altertable/altertable-js 0.5.2 | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
- function D(n,e){return(...t)=>[n,...t].join(e)}var w="https://api.altertable.ai",I="production",x="localStorage+cookie",ue="atbl",S=D(ue,"."),c=S("check"),P="session",U="visitor",de=1e3*60,N=100,L=30*de,$=1e3,V="$pageview",O="$lib",M="$lib_version",B="$referer",z="$release",F="$url",K="$viewport",i={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},T=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],y=new Set(["[object Object]","0","NaN","none","None","null"]);var h=class{_queue=[];_queueMaxSize;constructor(e){this._queueMaxSize=e}enqueue(e,t,s){this._queue.length>=this._queueMaxSize&&this._queue.shift(),this._queue.push({eventType:e,payload:t,context:s,sentAt:new Date})}flush(){let e=[...this._queue];return this._queue=[],e}clear(){this._queue=[]}getSize(){return this._queue.length}};function o(n,e=()=>{}){return typeof window>"u"?e():n({window})}function q(){return o(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function a(n,e){if(!n)throw new Error("Invariant failed")}function G(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v0.5.2 %c\u2022 Debug mode enabled";f.current[e]||(f.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[s,r]=_e(e.event),[g,l]=he(e.environment),[j,W]=Ee(e.timestamp),[H,J]=me(t);console.groupCollapsed(`[${n}] %c${s}%c [${g}] %c(${j}) %c${H}`,r,l,W,J);let[Z,ee]=k("User ID"),[te,ne]=b(e.user_id??"Not set"),[se,re]=k("Visitor ID"),[ie,oe]=b(e.visitor_id??"Not set"),[ae,ge]=k("Session ID"),[le,ce]=b(e.session_id??"Not set");console.log(`%c${Z} %c${te}`,ee,ne),console.log(`%c${se} %c${ie}`,re,oe),console.log(`%c${ae} %c${le}`,ge,ce),console.table(e.properties),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!r){f.current[s]=!0;let g=`[${n}] ${s}`;console.warn(g,...t);try{throw new Error(g)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var f={current:{}};function pe(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function _e(n){return[n,"background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;"]}function he(n){return[n,`color: ${fe(n)}; font-weight: 400;`]}function fe(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function Ee(n){return[pe(n),"color: #64748b; font-weight: 400;"]}function k(n){return[n,"color: #64748b; font-size: 11px;"]}function b(n){return[n,'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: "SF Mono", "Monaco", monospace; font-size: 11px;']}function me(n){switch(n){case i.GRANTED:return["",""];case i.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case i.PENDING:case i.DISMISSED:return["PENDING","background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];default:return["UNKNOWN","background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"]}}function C(n){if(typeof globalThis.crypto<"u"&&typeof globalThis.crypto.randomUUID=="function")try{return`${n}-${crypto.randomUUID()}`}catch{}return`${n}-${Math.random().toString(36).substring(2)}`}var E=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??i.PENDING,this._sessionData=this._createDefaultSessionData()}init(){let e=this._storage.getItem(this._storageKey);if(!e){this._sessionData=this._createDefaultSessionData(),this._persistToStorage();return}try{let t=JSON.parse(e);this._sessionData={visitorId:t.visitorId||this._generateVisitorId(),sessionId:t.sessionId||this._generateSessionId(),userId:t.userId||null,lastEventAt:t.lastEventAt||null,trackingConsent:ve(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getVisitorId(){return this._sessionData.visitorId}getSessionId(){return this._sessionData.sessionId}getUserId(){return this._sessionData.userId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}setUserId(e){this._sessionData.userId=e,this._persistToStorage()}setTrackingConsent(e){this._sessionData.trackingConsent=e,this._persistToStorage()}updateLastEventAt(e){this._sessionData.lastEventAt=e,this._persistToStorage()}renewSessionIfNeeded(){return this._shouldRenewSession()?(this._renewSession(),this._persistToStorage(),!0):!1}reset({resetVisitorId:e=!1,resetSessionId:t=!0,resetTrackingConsent:s=!1}={}){e&&(this._sessionData.visitorId=this._generateVisitorId()),t&&(this._sessionData.sessionId=this._generateSessionId()),s&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.userId=null,this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{visitorId:this._generateVisitorId(),sessionId:this._generateSessionId(),userId:null,lastEventAt:null,trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return C(P)}_generateVisitorId(){return C(U)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),s=new Date(e).getTime();return t-s>L}_renewSession(){this._sessionData.sessionId=this._generateSessionId(),this._sessionData.lastEventAt=null}_persistToStorage(){try{this._storage.setItem(this._storageKey,JSON.stringify(this._sessionData))}catch{this._logger.warnDev("Failed to persist session data to storage.")}}};function ve(n){return typeof n=="string"&&Object.values(i).includes(n)}function A(n,e,t){for(let s of t){let r=e.getItem(s);r!==null&&(n.setItem(s,r),e.removeItem(s))}}var u=class{store={};getItem(e){return this.store[e]??null}setItem(e,t){this.store[e]=t}removeItem(e){delete this.store[e]}migrate(e,t){A(this,e,t)}},_=class{getItem(e){return o(({window:t})=>{let s=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return s?decodeURIComponent(s[2]):null},()=>null)}setItem(e,t){o(({window:s})=>{s.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){o(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){A(this,e,t)}},d=class{constructor(e){this.storage=e}getItem(e){return o(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){o(({window:s})=>{try{s[this.storage].setItem(e,t)}catch{}})}removeItem(e){o(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){A(this,e,t)}},R=class{localStore=new d("localStorage");cookieStore=new _;getItem(e){return this.localStore.getItem(e)??this.cookieStore.getItem(e)}setItem(e,t){this.localStore.setItem(e,t),this.cookieStore.setItem(e,t)}removeItem(e){this.localStore.removeItem(e),this.cookieStore.removeItem(e)}migrate(e,t){for(let s of t){let r=e.getItem(s);r!==null&&(this.localStore.setItem(s,r),this.cookieStore.setItem(s,r))}for(let s of t)e.removeItem(s)}};function p(n){return o(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${c}=1`;let t=e.document.cookie.indexOf(`${c}=`)!==-1;return e.document.cookie=`${c}=; Max-Age=0`,t}else return e[n].setItem(c,"1"),e[n].removeItem(c),!0}catch{return!1}},()=>!1)}function m(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return p("localStorage")?new d("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),m("localStorage+cookie",e));case"localStorage+cookie":{let s=p("localStorage"),r=p("cookie");return s&&r?new R:r?(t("localStorage+cookie not fully supported, falling back to cookie."),new _):s?(t("cookie not supported, falling back to localStorage."),new d("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new u)}case"sessionStorage":return p("sessionStorage")?new d("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new u);case"cookie":return p("cookie")?new _:(t("cookie not supported, falling back to memory."),new u);case"memory":return new u;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Ie=[...T,...y].map(n=>`- "${n}"`).join(`
1
+ /*! @altertable/altertable-js 0.5.3 | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
+ function D(n,e){return(...t)=>[n,...t].join(e)}var w="https://api.altertable.ai",I="production",x="localStorage+cookie",ue="atbl",S=D(ue,"."),c=S("check"),P="session",U="visitor",de=1e3*60,N=100,L=30*de,$=1e3,V="$pageview",O="$lib",M="$lib_version",B="$referer",z="$release",F="$url",K="$viewport",i={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},T=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],y=new Set(["[object Object]","0","NaN","none","None","null"]);var h=class{_queue=[];_queueMaxSize;constructor(e){this._queueMaxSize=e}enqueue(e,t,s){this._queue.length>=this._queueMaxSize&&this._queue.shift(),this._queue.push({eventType:e,payload:t,context:s,sentAt:new Date})}flush(){let e=[...this._queue];return this._queue=[],e}clear(){this._queue=[]}getSize(){return this._queue.length}};function o(n,e=()=>{}){return typeof window>"u"?e():n({window})}function q(){return o(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function a(n,e){if(!n)throw new Error("Invariant failed")}function G(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v0.5.3 %c\u2022 Debug mode enabled";f.current[e]||(f.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[s,r]=_e(e.event),[g,l]=he(e.environment),[j,W]=Ee(e.timestamp),[H,J]=me(t);console.groupCollapsed(`[${n}] %c${s}%c [${g}] %c(${j}) %c${H}`,r,l,W,J);let[Z,ee]=k("User ID"),[te,ne]=b(e.user_id??"Not set"),[se,re]=k("Visitor ID"),[ie,oe]=b(e.visitor_id??"Not set"),[ae,ge]=k("Session ID"),[le,ce]=b(e.session_id??"Not set");console.log(`%c${Z} %c${te}`,ee,ne),console.log(`%c${se} %c${ie}`,re,oe),console.log(`%c${ae} %c${le}`,ge,ce),console.table(e.properties),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!r){f.current[s]=!0;let g=`[${n}] ${s}`;console.warn(g,...t);try{throw new Error(g)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var f={current:{}};function pe(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function _e(n){return[n,"background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;"]}function he(n){return[n,`color: ${fe(n)}; font-weight: 400;`]}function fe(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function Ee(n){return[pe(n),"color: #64748b; font-weight: 400;"]}function k(n){return[n,"color: #64748b; font-size: 11px;"]}function b(n){return[n,'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: "SF Mono", "Monaco", monospace; font-size: 11px;']}function me(n){switch(n){case i.GRANTED:return["",""];case i.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case i.PENDING:case i.DISMISSED:return["PENDING","background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];default:return["UNKNOWN","background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"]}}function C(n){if(typeof globalThis.crypto<"u"&&typeof globalThis.crypto.randomUUID=="function")try{return`${n}-${crypto.randomUUID()}`}catch{}return`${n}-${Math.random().toString(36).substring(2)}`}var E=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??i.PENDING,this._sessionData=this._createDefaultSessionData()}init(){let e=this._storage.getItem(this._storageKey);if(!e){this._sessionData=this._createDefaultSessionData(),this._persistToStorage();return}try{let t=JSON.parse(e);this._sessionData={visitorId:t.visitorId||this._generateVisitorId(),sessionId:t.sessionId||this._generateSessionId(),userId:t.userId||null,lastEventAt:t.lastEventAt||null,trackingConsent:ve(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getVisitorId(){return this._sessionData.visitorId}getSessionId(){return this._sessionData.sessionId}getUserId(){return this._sessionData.userId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}setUserId(e){this._sessionData.userId=e,this._persistToStorage()}setTrackingConsent(e){this._sessionData.trackingConsent=e,this._persistToStorage()}updateLastEventAt(e){this._sessionData.lastEventAt=e,this._persistToStorage()}renewSessionIfNeeded(){return this._shouldRenewSession()?(this._renewSession(),this._persistToStorage(),!0):!1}reset({resetVisitorId:e=!1,resetSessionId:t=!0,resetTrackingConsent:s=!1}={}){e&&(this._sessionData.visitorId=this._generateVisitorId()),t&&(this._sessionData.sessionId=this._generateSessionId()),s&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.userId=null,this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{visitorId:this._generateVisitorId(),sessionId:this._generateSessionId(),userId:null,lastEventAt:null,trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return C(P)}_generateVisitorId(){return C(U)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),s=new Date(e).getTime();return t-s>L}_renewSession(){this._sessionData.sessionId=this._generateSessionId(),this._sessionData.lastEventAt=null}_persistToStorage(){try{this._storage.setItem(this._storageKey,JSON.stringify(this._sessionData))}catch{this._logger.warnDev("Failed to persist session data to storage.")}}};function ve(n){return typeof n=="string"&&Object.values(i).includes(n)}function A(n,e,t){for(let s of t){let r=e.getItem(s);r!==null&&(n.setItem(s,r),e.removeItem(s))}}var u=class{store={};getItem(e){return this.store[e]??null}setItem(e,t){this.store[e]=t}removeItem(e){delete this.store[e]}migrate(e,t){A(this,e,t)}},_=class{getItem(e){return o(({window:t})=>{let s=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return s?decodeURIComponent(s[2]):null},()=>null)}setItem(e,t){o(({window:s})=>{s.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){o(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){A(this,e,t)}},d=class{constructor(e){this.storage=e}getItem(e){return o(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){o(({window:s})=>{try{s[this.storage].setItem(e,t)}catch{}})}removeItem(e){o(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){A(this,e,t)}},R=class{localStore=new d("localStorage");cookieStore=new _;getItem(e){return this.localStore.getItem(e)??this.cookieStore.getItem(e)}setItem(e,t){this.localStore.setItem(e,t),this.cookieStore.setItem(e,t)}removeItem(e){this.localStore.removeItem(e),this.cookieStore.removeItem(e)}migrate(e,t){for(let s of t){let r=e.getItem(s);r!==null&&(this.localStore.setItem(s,r),this.cookieStore.setItem(s,r))}for(let s of t)e.removeItem(s)}};function p(n){return o(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${c}=1`;let t=e.document.cookie.indexOf(`${c}=`)!==-1;return e.document.cookie=`${c}=; Max-Age=0`,t}else return e[n].setItem(c,"1"),e[n].removeItem(c),!0}catch{return!1}},()=>!1)}function m(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return p("localStorage")?new d("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),m("localStorage+cookie",e));case"localStorage+cookie":{let s=p("localStorage"),r=p("cookie");return s&&r?new R:r?(t("localStorage+cookie not fully supported, falling back to cookie."),new _):s?(t("cookie not supported, falling back to localStorage."),new d("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new u)}case"sessionStorage":return p("sessionStorage")?new d("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new u);case"cookie":return p("cookie")?new _:(t("cookie not supported, falling back to memory."),new u);case"memory":return new u;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Ie=[...T,...y].map(n=>`- "${n}"`).join(`
3
3
  `),Y=`List of reserved identifiers:
4
4
  ${Ie}`;function Q(n){if(!n||n.trim()==="")throw new Error("User ID cannot be empty or contain only whitespace.");if(T.some(s=>n.toLowerCase()===s.toLowerCase()))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
5
5
 
6
6
  `+Y);if(y.has(n))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
7
7
 
8
- `+Y)}var v=class{_apiKey;_cleanupAutoCapture;_config;_eventQueue;_isInitialized=!1;_lastUrl;_logger=G("Altertable");_referrer;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._eventQueue=new h($)}init(e,t={}){a(e,"Missing API key"),this._apiKey=e,this._config=t,this._storageKey=S(e,this._config.environment||I),this._referrer=o(({window:r})=>r.document.referrer||null,()=>null),this._lastUrl=o(({window:r})=>r.location.href||null,()=>null);let s=t.persistence??x;return this._storage=m(s,{onFallback:r=>this._logger.warn(r)}),this._sessionManager=new E({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:t.trackingConsent??i.PENDING}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader(),this._handleAutoCaptureChange(t.autoCapture??!0),()=>{this._cleanupAutoCapture?.()}}configure(e){if(a(this._isInitialized,"The client must be initialized with init() before configuring."),e.autoCapture!==void 0&&e.autoCapture!==this._config.autoCapture&&this._handleAutoCaptureChange(e.autoCapture),e.persistence!==void 0&&e.persistence!==this._config.persistence){let s=this._storage;this._storage=m(e.persistence,{onFallback:r=>this._logger.warn(r)}),this._storage.migrate(s,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();if(e.trackingConsent!==void 0&&e.trackingConsent!==t)if(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==i.GRANTED&&e.trackingConsent===i.GRANTED){let s=this._eventQueue.flush();s.length>0&&s.forEach(r=>{this._processEvent(r.eventType,r.payload,r.context)})}else e.trackingConsent===i.DENIED&&this._eventQueue.clear();this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),s=setInterval(t,N);o(({window:r})=>{r.addEventListener("popstate",t),r.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(s),o(({window:r})=>{r.removeEventListener("popstate",t),r.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){a(this._isInitialized,"The client must be initialized with init() before identifying users.");try{Q(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}this._sessionManager.setUserId(e);let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:t,user_id:e,visitor_id:s.visitor_id},s)}updateTraits(e){let t=this._sessionManager.getUserId();a(t,"User must be identified with identify() before updating traits.");let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:e,user_id:t,visitor_id:s.visitor_id},s)}reset({resetVisitorId:e=!1,resetSessionId:t=!0}={}){a(this._isInitialized,"The client must be initialized with init() before resetting."),this._sessionManager.reset({resetVisitorId:e,resetSessionId:t})}page(e){a(this._isInitialized,"The client must be initialized with init() before tracking page views.");let t=new URL(e),s=`${t.origin}${t.pathname}`;this.track(V,{[F]:s,[K]:q(),[B]:this._referrer,...Object.fromEntries(t.searchParams)})}track(e,t={}){a(this._isInitialized,"The client must be initialized with init() before tracking events."),this._sessionManager.renewSessionIfNeeded();let s=new Date().toISOString();this._sessionManager.updateLastEventAt(s);let r=this._getEventContext(),g={timestamp:s,event:e,environment:r.environment,user_id:r.user_id,session_id:r.session_id,visitor_id:r.visitor_id,properties:{[O]:"@altertable/altertable-js",[M]:"0.5.2",[z]:this._config.release,...t}};if(this._processEvent("track",g,r),this._config.debug){let l=this._sessionManager.getTrackingConsent();this._logger.logEvent(g,{trackingConsent:l})}}getTrackingConsent(){return this._sessionManager.getTrackingConsent()}_checkForChanges(){o(({window:e})=>{if(!this._config.autoCapture)return;let t=e.location.href;t!==this._lastUrl&&(this.page(t),this._referrer=this._lastUrl,this._lastUrl=t)})}_getEventContext(){return{environment:this._config.environment||I,user_id:this._sessionManager.getUserId(),visitor_id:this._sessionManager.getVisitorId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t,s){switch(this._sessionManager.getTrackingConsent()){case i.GRANTED:this._request(`/${e}`,t);break;case i.PENDING:case i.DISMISSED:this._eventQueue.enqueue(e,t,s);break;case i.DENIED:break}}_request(e,t){a(this._apiKey,"Missing API key"),a(this._config,"Missing configuration");let s=`${this._config.baseUrl||w}${e}`,r=JSON.stringify(t);if(typeof navigator<"u"&&navigator.sendBeacon){let g=`${s}?apiKey=${encodeURIComponent(this._apiKey)}`,l=new Blob([r],{type:"application/json"});navigator.sendBeacon(g,l)}else fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:r})}};var X=new v;o(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let s=t[0],r=t.slice(1);X[s](...r)}n.Altertable=X});export{i as TrackingConsent,X as altertable};
8
+ `+Y)}var v=class{_apiKey;_cleanupAutoCapture;_config;_eventQueue;_isInitialized=!1;_lastUrl;_logger=G("Altertable");_referrer;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._eventQueue=new h($)}init(e,t={}){a(e,"Missing API key"),this._apiKey=e,this._config=t,this._storageKey=S(e,this._config.environment||I),this._referrer=o(({window:r})=>r.document.referrer||null,()=>null),this._lastUrl=o(({window:r})=>r.location.href||null,()=>null);let s=t.persistence??x;return this._storage=m(s,{onFallback:r=>this._logger.warn(r)}),this._sessionManager=new E({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:t.trackingConsent??i.PENDING}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader(),this._handleAutoCaptureChange(t.autoCapture??!0),()=>{this._cleanupAutoCapture?.()}}configure(e){if(a(this._isInitialized,"The client must be initialized with init() before configuring."),e.autoCapture!==void 0&&e.autoCapture!==this._config.autoCapture&&this._handleAutoCaptureChange(e.autoCapture),e.persistence!==void 0&&e.persistence!==this._config.persistence){let s=this._storage;this._storage=m(e.persistence,{onFallback:r=>this._logger.warn(r)}),this._storage.migrate(s,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();if(e.trackingConsent!==void 0&&e.trackingConsent!==t)if(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==i.GRANTED&&e.trackingConsent===i.GRANTED){let s=this._eventQueue.flush();s.length>0&&s.forEach(r=>{this._processEvent(r.eventType,r.payload,r.context)})}else e.trackingConsent===i.DENIED&&this._eventQueue.clear();this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),s=setInterval(t,N);o(({window:r})=>{r.addEventListener("popstate",t),r.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(s),o(({window:r})=>{r.removeEventListener("popstate",t),r.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){a(this._isInitialized,"The client must be initialized with init() before identifying users.");try{Q(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}this._sessionManager.setUserId(e);let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:t,user_id:e,visitor_id:s.visitor_id},s)}updateTraits(e){let t=this._sessionManager.getUserId();a(t,"User must be identified with identify() before updating traits.");let s=this._getEventContext();this._processEvent("identify",{environment:s.environment,traits:e,user_id:t,visitor_id:s.visitor_id},s)}reset({resetVisitorId:e=!1,resetSessionId:t=!0}={}){a(this._isInitialized,"The client must be initialized with init() before resetting."),this._sessionManager.reset({resetVisitorId:e,resetSessionId:t})}page(e){a(this._isInitialized,"The client must be initialized with init() before tracking page views.");let t=new URL(e),s=`${t.origin}${t.pathname}`;this.track(V,{[F]:s,[K]:q(),[B]:this._referrer,...Object.fromEntries(t.searchParams)})}track(e,t={}){a(this._isInitialized,"The client must be initialized with init() before tracking events."),this._sessionManager.renewSessionIfNeeded();let s=new Date().toISOString();this._sessionManager.updateLastEventAt(s);let r=this._getEventContext(),g={timestamp:s,event:e,environment:r.environment,user_id:r.user_id,session_id:r.session_id,visitor_id:r.visitor_id,properties:{[O]:"@altertable/altertable-js",[M]:"0.5.3",[z]:this._config.release,...t}};if(this._processEvent("track",g,r),this._config.debug){let l=this._sessionManager.getTrackingConsent();this._logger.logEvent(g,{trackingConsent:l})}}getTrackingConsent(){return this._sessionManager.getTrackingConsent()}_checkForChanges(){o(({window:e})=>{let t=e.location.href;t!==this._lastUrl&&(this.page(t),this._referrer=this._lastUrl,this._lastUrl=t)})}_getEventContext(){return{environment:this._config.environment||I,user_id:this._sessionManager.getUserId(),visitor_id:this._sessionManager.getVisitorId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t,s){switch(this._sessionManager.getTrackingConsent()){case i.GRANTED:this._request(`/${e}`,t);break;case i.PENDING:case i.DISMISSED:this._eventQueue.enqueue(e,t,s);break;case i.DENIED:break}}_request(e,t){a(this._apiKey,"Missing API key"),a(this._config,"Missing configuration");let s=`${this._config.baseUrl||w}${e}`,r=JSON.stringify(t);if(typeof navigator<"u"&&navigator.sendBeacon){let g=`${s}?apiKey=${encodeURIComponent(this._apiKey)}`,l=new Blob([r],{type:"application/json"});navigator.sendBeacon(g,l)}else fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:r})}};var X=new v;o(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let s=t[0],r=t.slice(1);X[s](...r)}n.Altertable=X});export{i as TrackingConsent,X as altertable};
9
9
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/createKeyBuilder.ts","../src/constants.ts","../src/lib/eventQueue.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/getViewport.ts","../src/lib/invariant.ts","../src/lib/logger.ts","../src/lib/generateId.ts","../src/lib/sessionManager.ts","../src/lib/storage.ts","../src/lib/validateUserId.ts","../src/core.ts","../src/index.ts"],"sourcesContent":["export function createKeyBuilder(prefix: string, separator: string) {\n return (...parts: string[]) => {\n return [prefix, ...parts].join(separator);\n };\n}\n","import { createKeyBuilder } from './lib/createKeyBuilder';\n\nexport const DEFAULT_BASE_URL = 'https://api.altertable.ai';\nexport const DEFAULT_ENVIRONMENT = 'production';\nexport const DEFAULT_PERSISTENCE = 'localStorage+cookie';\n\nconst STORAGE_KEY_PREFIX = 'atbl';\nexport const keyBuilder = createKeyBuilder(STORAGE_KEY_PREFIX, '.');\nexport const STORAGE_KEY_TEST = keyBuilder('check');\n\nexport const PREFIX_SESSION_ID = 'session';\nexport const PREFIX_VISITOR_ID = 'visitor';\n\nconst MINUTE_IN_MS = 1000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_EVENT_QUEUE_SIZE = 1000;\n\nexport const EVENT_PAGEVIEW = '$pageview';\n\nexport const PROPERTY_LIB = '$lib';\nexport const PROPERTY_LIB_VERSION = '$lib_version';\nexport const PROPERTY_REFERER = '$referer';\nexport const PROPERTY_RELEASE = '$release';\nexport const PROPERTY_URL = '$url';\nexport const PROPERTY_VIEWPORT = '$viewport';\n\nexport const TrackingConsent = {\n DENIED: 'denied',\n DISMISSED: 'dismissed',\n GRANTED: 'granted',\n PENDING: 'pending',\n} as const;\n\nexport type TrackingConsentType =\n (typeof TrackingConsent)[keyof typeof TrackingConsent];\n\nexport const RESERVED_USER_IDS = [\n 'anonymous_id',\n 'anonymous',\n 'distinct_id',\n 'distinctid',\n 'false',\n 'guest',\n 'id',\n 'not_authenticated',\n 'true',\n 'undefined',\n 'user_id',\n 'user',\n 'visitor_id',\n 'visitor',\n];\nexport const RESERVED_USER_IDS_CASE_SENSITIVE = new Set([\n '[object Object]',\n '0',\n 'NaN',\n 'none',\n 'None',\n 'null',\n]);\n","import type { EventContext, EventType } from '../types';\n\ntype QueuedEvent<TPayload> = {\n eventType: EventType;\n payload: TPayload;\n sentAt: Date;\n context: EventContext;\n};\n\nexport class EventQueue<TPayload> {\n private _queue: QueuedEvent<TPayload>[] = [];\n private _queueMaxSize: number;\n\n constructor(queueMaxSize: number) {\n this._queueMaxSize = queueMaxSize;\n }\n\n enqueue(\n eventType: 'track' | 'identify',\n payload: TPayload,\n context: EventContext\n ): void {\n if (this._queue.length >= this._queueMaxSize) {\n // Remove oldest event to make room for new one\n this._queue.shift();\n }\n this._queue.push({\n eventType,\n payload,\n context,\n sentAt: new Date(),\n });\n }\n\n flush(): Array<QueuedEvent<TPayload>> {\n const events = [...this._queue];\n this._queue = [];\n return events;\n }\n\n clear(): void {\n this._queue = [];\n }\n\n getSize(): number {\n return this._queue.length;\n }\n}\n","/* eslint-disable no-restricted-globals */\n\n/** Runs code on browser environments safely. */\nexport function safelyRunOnBrowser<TReturn>(\n callback: (params: { window: typeof window }) => TReturn,\n /** Fallback to run on server environments. */\n fallback: () => TReturn = () => undefined as unknown as TReturn\n): TReturn {\n if (typeof window === 'undefined') {\n return fallback();\n }\n\n return callback({ window });\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport function getViewport(): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","/**\n * Throws an error if the condition is not met.\n *\n * The error is exhaustive in development, and becomes generic in production.\n *\n * This is used to make development a better experience to provide guidance as\n * to where the error comes from.\n */\nexport function invariant(\n condition: unknown,\n message: string | (() => string)\n): asserts condition {\n if (condition) {\n return;\n }\n\n if (__DEV__) {\n throw new Error(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n }\n\n throw new Error('Invariant failed');\n}\n","/* eslint-disable no-console */\n\nimport { TrackingConsent, TrackingConsentType } from '../constants';\nimport { EventPayload } from '../types';\n\nexport type Logger = ReturnType<typeof createLogger>;\n\nexport function createLogger(prefix: string) {\n return {\n log: (...args: unknown[]) => {\n console.log(`[${prefix}]`, ...args);\n },\n logHeader: () => {\n const header = `Altertable v${__LIB_VERSION__} %c• Debug mode enabled`;\n const hasAlreadyPrinted = loggerCache.current[header];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[header] = true;\n console.log(header, 'color: #64748b;');\n }\n },\n logEvent: (\n payload: EventPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event\n );\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [timestampLabel, timestampStyle] = createTimestampElement(\n payload.timestamp\n );\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c [${environmentBadgeLabel}] %c(${timestampLabel}) %c${consentBadgeLabel}`,\n eventBadgeStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabelLabel, userLabelStyle] = createLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.user_id ?? 'Not set'\n );\n const [visitorLabelLabel, visitorLabelStyle] =\n createLabelElement('Visitor ID');\n const [visitorValueLabel, visitorValueStyle] = createValueElement(\n payload.visitor_id ?? 'Not set'\n );\n const [sessionLabelLabel, sessionLabelStyle] =\n createLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabelLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${visitorLabelLabel} %c${visitorValueLabel}`,\n visitorLabelStyle,\n visitorValueStyle\n );\n console.log(\n `%c${sessionLabelLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n warn: (...args: unknown[]) => {\n console.warn(`[${prefix}]`, ...args);\n },\n warnDev: (message: string, ...args: unknown[]) => {\n if (!__DEV__) {\n return;\n }\n\n const sanitizedMessage = message.trim();\n const hasAlreadyPrinted = loggerCache.current[sanitizedMessage];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[sanitizedMessage] = true;\n const warning = `[${prefix}] ${sanitizedMessage}`;\n\n console.warn(warning, ...args);\n\n try {\n // Welcome to debugging Altertable.\n //\n // This error was thrown as a convenience so that you can find the source\n // of the warning that appears in the console by enabling \"Pause on exceptions\"\n // in your debugger.\n throw new Error(warning);\n } catch (error) {\n // Do nothing\n }\n }\n },\n error: (...args: unknown[]) => {\n console.error(`[${prefix}]`, ...args);\n },\n };\n}\n\nexport const loggerCache: { current: Record<string, boolean> } = {\n current: {},\n};\n\nfunction formatEventTime(timestamp: string) {\n return new Date(timestamp).toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction createEventBadgeElement(value: string): [string, string] {\n return [\n value,\n 'background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;',\n ];\n}\n\nfunction createEnvironmentBadgeElement(value: string): [string, string] {\n return [value, `color: ${getEnvironmentColor(value)}; font-weight: 400;`];\n}\n\nfunction getEnvironmentColor(environment: string) {\n const formattedEnv = environment.toLocaleLowerCase().startsWith('prod')\n ? 'production'\n : environment;\n\n switch (formattedEnv) {\n case 'production':\n return '#ef4444';\n default:\n return '#3b82f6';\n }\n}\n\nfunction createTimestampElement(value: string): [string, string] {\n return [formatEventTime(value), 'color: #64748b; font-weight: 400;'];\n}\n\nfunction createLabelElement(value: string): [string, string] {\n return [value, 'color: #64748b; font-size: 11px;'];\n}\n\nfunction createValueElement(value: string): [string, string] {\n return [\n value,\n 'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: \"SF Mono\", \"Monaco\", monospace; font-size: 11px;',\n ];\n}\n\nfunction getConsentBadgeElement(\n trackingConsent: TrackingConsentType\n): [string, string] {\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n return ['', ''];\n case TrackingConsent.DENIED:\n return [\n 'DENIED',\n 'background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n return [\n 'PENDING',\n 'background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n default:\n return [\n 'UNKNOWN',\n 'background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n }\n}\n","export function generateId<T extends string>(prefix: T): `${T}-${string}` {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n try {\n return `${prefix}-${crypto.randomUUID()}`;\n } catch {\n // Continue with Math.random() fallback.\n }\n }\n return `${prefix}-${Math.random().toString(36).substring(2)}`;\n}\n","import {\n PREFIX_SESSION_ID,\n PREFIX_VISITOR_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\nimport type { UserId, VisitorId, SessionId } from '../types';\n\ntype SessionData = {\n visitorId: VisitorId;\n sessionId: SessionId;\n userId: UserId | null;\n lastEventAt: string | null;\n trackingConsent: TrackingConsentType;\n};\n\nexport class SessionManager {\n private _defaultTrackingConsent: TrackingConsentType;\n private _logger: Logger;\n private _sessionData: SessionData;\n private _storage: StorageApi;\n private _storageKey: string;\n\n constructor(options: {\n storage: StorageApi;\n storageKey: string;\n logger: Logger;\n defaultTrackingConsent: TrackingConsentType;\n }) {\n this._storage = options.storage;\n this._storageKey = options.storageKey;\n this._logger = options.logger;\n this._defaultTrackingConsent =\n options.defaultTrackingConsent ?? TrackingConsent.PENDING;\n this._sessionData = this._createDefaultSessionData();\n }\n\n init(): void {\n const storedData = this._storage.getItem(this._storageKey);\n\n if (!storedData) {\n this._sessionData = this._createDefaultSessionData();\n this._persistToStorage();\n return;\n }\n\n try {\n const parsedData = JSON.parse(storedData) as Partial<SessionData>;\n\n this._sessionData = {\n visitorId: parsedData.visitorId || this._generateVisitorId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n userId: parsedData.userId || null,\n lastEventAt: parsedData.lastEventAt || null,\n trackingConsent: isValidTrackingConsent(parsedData.trackingConsent)\n ? parsedData.trackingConsent\n : this._defaultTrackingConsent,\n };\n } catch (error) {\n this._logger.warnDev(\n 'Failed to parse storage data. Resetting session data.'\n );\n this._sessionData = this._createDefaultSessionData();\n }\n\n this._persistToStorage();\n }\n\n getVisitorId(): VisitorId {\n return this._sessionData.visitorId;\n }\n\n getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getUserId(): UserId | null {\n return this._sessionData.userId;\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n setUserId(userId: UserId | null): void {\n this._sessionData.userId = userId;\n this._persistToStorage();\n }\n\n setTrackingConsent(consent: TrackingConsentType): void {\n this._sessionData.trackingConsent = consent;\n this._persistToStorage();\n }\n\n updateLastEventAt(timestamp: string): void {\n this._sessionData.lastEventAt = timestamp;\n this._persistToStorage();\n }\n\n renewSessionIfNeeded(): boolean {\n const shouldRenew = this._shouldRenewSession();\n\n if (shouldRenew) {\n this._renewSession();\n this._persistToStorage();\n return true;\n }\n\n return false;\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n resetTrackingConsent = false,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetVisitorId) {\n this._sessionData.visitorId = this._generateVisitorId();\n }\n\n if (resetSessionId) {\n this._sessionData.sessionId = this._generateSessionId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.userId = null;\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n visitorId: this._generateVisitorId(),\n sessionId: this._generateSessionId(),\n userId: null,\n lastEventAt: null,\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateVisitorId(): VisitorId {\n return generateId(PREFIX_VISITOR_ID);\n }\n\n private _shouldRenewSession(): boolean {\n const { lastEventAt } = this._sessionData;\n\n if (!lastEventAt) {\n return true;\n }\n\n const now = new Date().getTime();\n const lastEventTime = new Date(lastEventAt).getTime();\n const timeSinceLastEvent = now - lastEventTime;\n\n return timeSinceLastEvent > SESSION_EXPIRATION_TIME_MS;\n }\n\n private _renewSession(): void {\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.lastEventAt = null;\n }\n\n private _persistToStorage(): void {\n try {\n this._storage.setItem(\n this._storageKey,\n JSON.stringify(this._sessionData)\n );\n } catch (error) {\n this._logger.warnDev('Failed to persist session data to storage.');\n }\n }\n}\n\nfunction isValidTrackingConsent(value: unknown): value is TrackingConsentType {\n return (\n typeof value === 'string' &&\n Object.values(TrackingConsent).includes(value as TrackingConsentType)\n );\n}\n","import { STORAGE_KEY_TEST } from '../constants';\nimport { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport type StorageType =\n | 'localStorage'\n | 'sessionStorage'\n | 'cookie'\n | 'memory'\n | 'localStorage+cookie';\n\nexport interface StorageApi {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n migrate(fromStorage: StorageApi, keys: string[]): void;\n}\n\nfunction migrateKeys(\n toStorage: StorageApi,\n fromStorage: StorageApi,\n keys: string[]\n): void {\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n toStorage.setItem(key, value);\n fromStorage.removeItem(key);\n }\n }\n}\n\nclass MemoryStore implements StorageApi {\n private store: Record<string, string> = {};\n getItem(key: string): string | null {\n return this.store[key] ?? null;\n }\n setItem(key: string, value: string) {\n this.store[key] = value;\n }\n removeItem(key: string) {\n delete this.store[key];\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass CookieStore implements StorageApi {\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n const match = window.document.cookie.match(\n new RegExp('(^| )' + key + '=([^;]+)')\n );\n return match ? decodeURIComponent(match[2]) : null;\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=${encodeURIComponent(value)}; path=/;`;\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=; Max-Age=0; path=/;`;\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass WebStorageStore implements StorageApi {\n constructor(private storage: 'localStorage' | 'sessionStorage') {}\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n try {\n return window[this.storage].getItem(key);\n } catch {\n return null;\n }\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].setItem(key, value);\n } catch {\n /* ignore */\n }\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].removeItem(key);\n } catch {\n /* ignore */\n }\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass LocalPlusCookieStore implements StorageApi {\n private localStore = new WebStorageStore('localStorage');\n private cookieStore = new CookieStore();\n getItem(key: string): string | null {\n return this.localStore.getItem(key) ?? this.cookieStore.getItem(key);\n }\n setItem(key: string, value: string) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n removeItem(key: string) {\n this.localStore.removeItem(key);\n this.cookieStore.removeItem(key);\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n // Migrate to both localStorage and cookie without removing from source yet\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n }\n\n for (const key of keys) {\n fromStorage.removeItem(key);\n }\n }\n}\n\nfunction testStorageSupport(\n storageType: 'localStorage' | 'sessionStorage' | 'cookie'\n) {\n return safelyRunOnBrowser(\n ({ window }) => {\n try {\n if (storageType === 'cookie') {\n window.document.cookie = `${STORAGE_KEY_TEST}=1`;\n const supported =\n window.document.cookie.indexOf(`${STORAGE_KEY_TEST}=`) !== -1;\n window.document.cookie = `${STORAGE_KEY_TEST}=; Max-Age=0`;\n return supported;\n } else {\n window[storageType].setItem(STORAGE_KEY_TEST, '1');\n window[storageType].removeItem(STORAGE_KEY_TEST);\n return true;\n }\n } catch {\n return false;\n }\n },\n () => false\n );\n}\n\nexport function selectStorage(\n type: StorageType | 'unknown',\n params: { onFallback: (message: string) => void }\n): StorageApi {\n const { onFallback } = params;\n\n switch (type) {\n case 'localStorage': {\n if (testStorageSupport('localStorage')) {\n return new WebStorageStore('localStorage');\n }\n onFallback(\n 'localStorage not supported, falling back to localStorage+cookie.'\n );\n return selectStorage('localStorage+cookie', params);\n }\n\n case 'localStorage+cookie': {\n const localStorageSupported = testStorageSupport('localStorage');\n const cookieSupported = testStorageSupport('cookie');\n\n if (localStorageSupported && cookieSupported) {\n return new LocalPlusCookieStore();\n } else if (cookieSupported) {\n onFallback(\n 'localStorage+cookie not fully supported, falling back to cookie.'\n );\n return new CookieStore();\n } else if (localStorageSupported) {\n onFallback('cookie not supported, falling back to localStorage.');\n return new WebStorageStore('localStorage');\n } else {\n onFallback(\n 'Neither localStorage nor cookie supported, falling back to memory.'\n );\n return new MemoryStore();\n }\n }\n\n case 'sessionStorage': {\n if (testStorageSupport('sessionStorage')) {\n return new WebStorageStore('sessionStorage');\n }\n onFallback('sessionStorage not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'cookie': {\n if (testStorageSupport('cookie')) {\n return new CookieStore();\n }\n onFallback('cookie not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'memory': {\n return new MemoryStore();\n }\n\n default: {\n throw new Error(\n `Unknown storage type: \"${type}\". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`\n );\n }\n }\n}\n","import {\n RESERVED_USER_IDS,\n RESERVED_USER_IDS_CASE_SENSITIVE,\n} from '../constants';\n\nconst reservedIdentifiersList = [\n ...RESERVED_USER_IDS,\n ...RESERVED_USER_IDS_CASE_SENSITIVE,\n]\n .map(id => `- \"${id}\"`)\n .join('\\n');\nconst reservedIdentifiersInfo = `List of reserved identifiers:\\n${reservedIdentifiersList}`;\n\nexport function validateUserId(userId: string): void {\n if (!userId || userId.trim() === '') {\n throw new Error('User ID cannot be empty or contain only whitespace.');\n }\n\n const isCaseInsensitiveBlocked = RESERVED_USER_IDS.some(\n blockedId => userId.toLowerCase() === blockedId.toLowerCase()\n );\n\n if (isCaseInsensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n\n const isCaseSensitiveBlocked = RESERVED_USER_IDS_CASE_SENSITIVE.has(userId);\n\n if (isCaseSensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n}\n","import {\n AUTO_CAPTURE_INTERVAL_MS,\n DEFAULT_BASE_URL,\n DEFAULT_ENVIRONMENT,\n DEFAULT_PERSISTENCE,\n EVENT_PAGEVIEW,\n keyBuilder,\n MAX_EVENT_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { EventQueue } from './lib/eventQueue';\nimport { getViewport } from './lib/getViewport';\nimport { invariant } from './lib/invariant';\nimport { createLogger } from './lib/logger';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\nimport { SessionManager } from './lib/sessionManager';\nimport {\n selectStorage,\n type StorageApi,\n type StorageType,\n} from './lib/storage';\nimport { validateUserId } from './lib/validateUserId';\nimport {\n EventContext,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n UserTraits,\n} from './types';\n\nexport interface AltertableConfig {\n /**\n * The base URL of the Altertable API.\n * @default https://api.altertable.ai\n */\n baseUrl?: string;\n /**\n * The environment of the application.\n * @default \"production\"\n */\n environment?: string;\n /**\n * Whether to automatically capture page views and events.\n * @default true\n */\n autoCapture?: boolean;\n /**\n * The release ID of the application.\n * This is helpful to identify the version of the application an event is coming from.\n */\n release?: string;\n /**\n * Whether to log events to the console.\n * @default false\n */\n debug?: boolean;\n /**\n * The persistence strategy for storing IDs.\n * @default \"localStorage+cookie\"\n */\n persistence?: StorageType;\n /**\n * The tracking consent state.\n * @default \"pending\"\n */\n trackingConsent?: TrackingConsentType;\n}\n\nexport class Altertable {\n private _apiKey: string;\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _eventQueue: EventQueue<EventPayload | IdentifyPayload>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _sessionManager: SessionManager | undefined;\n private _storage: StorageApi | undefined;\n private _storageKey: string | undefined;\n\n constructor() {\n this._lastUrl = null;\n this._referrer = null;\n this._eventQueue = new EventQueue(MAX_EVENT_QUEUE_SIZE);\n }\n\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._apiKey = apiKey;\n this._config = config;\n this._storageKey = keyBuilder(\n apiKey,\n this._config.environment || DEFAULT_ENVIRONMENT\n );\n this._referrer = safelyRunOnBrowser<string | null>(\n ({ window }) => window.document.referrer || null,\n () => null\n );\n this._lastUrl = safelyRunOnBrowser<string | null>(\n ({ window }) => window.location.href || null,\n () => null\n );\n const persistence: StorageType = config.persistence ?? DEFAULT_PERSISTENCE;\n this._storage = selectStorage(persistence, {\n onFallback: message => this._logger.warn(message),\n });\n\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: config.trackingConsent ?? TrackingConsent.PENDING,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n this._handleAutoCaptureChange(config.autoCapture ?? true);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n configure(updates: Partial<AltertableConfig>) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before configuring.'\n );\n\n if (\n updates.autoCapture !== undefined &&\n updates.autoCapture !== this._config.autoCapture\n ) {\n this._handleAutoCaptureChange(updates.autoCapture);\n }\n\n if (\n updates.persistence !== undefined &&\n updates.persistence !== this._config.persistence\n ) {\n const previousStorage = this._storage;\n this._storage = selectStorage(updates.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._storage.migrate(previousStorage, [this._storageKey]);\n }\n\n const currentTrackingConsent = this._sessionManager.getTrackingConsent();\n if (\n updates.trackingConsent !== undefined &&\n updates.trackingConsent !== currentTrackingConsent\n ) {\n this._sessionManager.setTrackingConsent(updates.trackingConsent);\n\n if (\n currentTrackingConsent !== TrackingConsent.GRANTED &&\n updates.trackingConsent === TrackingConsent.GRANTED\n ) {\n const queuedEvents = this._eventQueue.flush();\n if (queuedEvents.length > 0) {\n queuedEvents.forEach(event => {\n this._processEvent(event.eventType, event.payload, event.context);\n });\n }\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._eventQueue.clear();\n }\n }\n\n this._config = { ...this._config, ...updates };\n }\n\n private _handleAutoCaptureChange(enableAutoCapture: boolean) {\n this._cleanupAutoCapture?.();\n\n if (enableAutoCapture) {\n if (this._lastUrl) {\n this.page(this._lastUrl);\n }\n\n const checkForChanges = this._checkForChanges.bind(this);\n const intervalId = setInterval(checkForChanges, AUTO_CAPTURE_INTERVAL_MS);\n\n safelyRunOnBrowser(({ window }) => {\n window.addEventListener('popstate', checkForChanges);\n window.addEventListener('hashchange', checkForChanges);\n });\n\n this._cleanupAutoCapture = () => {\n clearInterval(intervalId);\n safelyRunOnBrowser(({ window }) => {\n window.removeEventListener('popstate', checkForChanges);\n window.removeEventListener('hashchange', checkForChanges);\n });\n };\n } else {\n this._cleanupAutoCapture = undefined;\n }\n }\n\n identify(userId: string, traits: UserTraits = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before identifying users.'\n );\n\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n this._sessionManager.setUserId(userId);\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n updateTraits(traits: UserTraits) {\n const userId = this._sessionManager.getUserId();\n invariant(\n userId,\n 'User must be identified with identify() before updating traits.'\n );\n\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n } = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before resetting.'\n );\n\n this._sessionManager.reset({ resetVisitorId, resetSessionId });\n }\n\n page(url: string) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking page views.'\n );\n\n const parsedUrl = new URL(url);\n const urlWithoutSearch = `${parsedUrl.origin}${parsedUrl.pathname}`;\n this.track(EVENT_PAGEVIEW, {\n [PROPERTY_URL]: urlWithoutSearch,\n [PROPERTY_VIEWPORT]: getViewport(),\n [PROPERTY_REFERER]: this._referrer,\n ...Object.fromEntries(parsedUrl.searchParams),\n });\n }\n\n track(event: string, properties: EventProperties = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking events.'\n );\n\n this._sessionManager.renewSessionIfNeeded();\n const timestamp = new Date().toISOString();\n this._sessionManager.updateLastEventAt(timestamp);\n\n const context = this._getEventContext();\n const payload: EventPayload = {\n timestamp,\n event,\n environment: context.environment,\n user_id: context.user_id,\n session_id: context.session_id,\n visitor_id: context.visitor_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...properties,\n },\n };\n\n this._processEvent('track', payload, context);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionManager.getTrackingConsent();\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n if (!this._config.autoCapture) {\n return;\n }\n\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this.page(currentUrl);\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n }\n });\n }\n\n private _getEventContext(): EventContext {\n return {\n environment: this._config.environment || DEFAULT_ENVIRONMENT,\n user_id: this._sessionManager.getUserId(),\n visitor_id: this._sessionManager.getVisitorId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload | IdentifyPayload>(\n eventType: EventType,\n payload: TPayload,\n context: EventContext\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._request(`/${eventType}`, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._eventQueue.enqueue(eventType, payload, context);\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private _request(path: string, body: unknown): void {\n invariant(this._apiKey, 'Missing API key');\n invariant(this._config, 'Missing configuration');\n\n const url = `${this._config.baseUrl || DEFAULT_BASE_URL}${path}`;\n const payload = JSON.stringify(body);\n\n /* eslint-disable no-restricted-globals */\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n const beaconUrl = `${url}?apiKey=${encodeURIComponent(this._apiKey)}`;\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(beaconUrl, blob);\n } /* eslint-enable no-restricted-globals */ else {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._apiKey}`,\n },\n body: payload,\n });\n }\n }\n}\n","import { TrackingConsent } from './constants';\nimport { Altertable, type AltertableConfig } from './core';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\n\nexport type { Altertable, AltertableConfig };\nexport { TrackingConsent };\n\ndeclare global {\n interface Window {\n Altertable: Altertable | Array<Array<unknown>> | undefined;\n }\n}\n\nexport const altertable = new Altertable();\n\nsafelyRunOnBrowser(({ window }) => {\n const stub = window.Altertable;\n if (stub && Array.isArray(stub)) {\n for (const item of stub) {\n const method = item[0];\n const args = item.slice(1);\n (altertable[method as keyof Altertable] as any)(...args);\n }\n }\n\n window.Altertable = altertable;\n});\n"],"mappings":";AAAO,SAASA,EAAiBC,EAAgBC,EAAmB,CAClE,MAAO,IAAIC,IACF,CAACF,EAAQ,GAAGE,CAAK,EAAE,KAAKD,CAAS,CAE5C,CCFO,IAAME,EAAmB,4BACnBC,EAAsB,aACtBC,EAAsB,sBAE7BC,GAAqB,OACdC,EAAaC,EAAiBF,GAAoB,GAAG,EACrDG,EAAmBF,EAAW,OAAO,EAErCG,EAAoB,UACpBC,EAAoB,UAE3BC,GAAe,IAAO,GACfC,EAA2B,IAC3BC,EAA6B,GAAKF,GAClCG,EAAuB,IAEvBC,EAAiB,YAEjBC,EAAe,OACfC,EAAuB,eACvBC,EAAmB,WACnBC,EAAmB,WACnBC,EAAe,OACfC,EAAoB,YAEpBC,EAAkB,CAC7B,OAAQ,SACR,UAAW,YACX,QAAS,UACT,QAAS,SACX,EAKaC,EAAoB,CAC/B,eACA,YACA,cACA,aACA,QACA,QACA,KACA,oBACA,OACA,YACA,UACA,OACA,aACA,SACF,EACaC,EAAmC,IAAI,IAAI,CACtD,kBACA,IACA,MACA,OACA,OACA,MACF,CAAC,ECnDM,IAAMC,EAAN,KAA2B,CACxB,OAAkC,CAAC,EACnC,cAER,YAAYC,EAAsB,CAChC,KAAK,cAAgBA,CACvB,CAEA,QACEC,EACAC,EACAC,EACM,CACF,KAAK,OAAO,QAAU,KAAK,eAE7B,KAAK,OAAO,MAAM,EAEpB,KAAK,OAAO,KAAK,CACf,UAAAF,EACA,QAAAC,EACA,QAAAC,EACA,OAAQ,IAAI,IACd,CAAC,CACH,CAEA,OAAsC,CACpC,IAAMC,EAAS,CAAC,GAAG,KAAK,MAAM,EAC9B,YAAK,OAAS,CAAC,EACRA,CACT,CAEA,OAAc,CACZ,KAAK,OAAS,CAAC,CACjB,CAEA,SAAkB,CAChB,OAAO,KAAK,OAAO,MACrB,CACF,EC5CO,SAASC,EACdC,EAEAC,EAA0B,IAAG,GACpB,CACT,OAAI,OAAO,OAAW,IACbA,EAAS,EAGXD,EAAS,CAAE,MAAO,CAAC,CAC5B,CCXO,SAASE,GAA6B,CAC3C,OAAOC,EACL,CAAC,CAAE,OAAAC,CAAO,IAAM,GAAGA,EAAO,UAAU,IAAIA,EAAO,WAAW,GAC1D,IAAM,IACR,CACF,CCCO,SAASC,EACdC,EACAC,EACmB,CACnB,GAAI,CAAAD,EAUJ,MAAM,IAAI,MAAM,kBAAkB,CACpC,CChBO,SAASE,EAAaC,EAAgB,CAC3C,MAAO,CACL,IAAK,IAAIC,IAAoB,CAC3B,QAAQ,IAAI,IAAID,CAAM,IAAK,GAAGC,CAAI,CACpC,EACA,UAAW,IAAM,CACf,IAAMC,EAAS,gDACWC,EAAY,QAAQD,CAAM,IAGlDC,EAAY,QAAQD,CAAM,EAAI,GAC9B,QAAQ,IAAIA,EAAQ,iBAAiB,EAEzC,EACA,SAAU,CACRE,EACA,CAAE,gBAAAC,CAAgB,IACf,CACH,GAAM,CAACC,EAAiBC,CAAe,EAAIC,GACzCJ,EAAQ,KACV,EACM,CAACK,EAAuBC,CAAqB,EACjDC,GAA8BP,EAAQ,WAAW,EAC7C,CAACQ,EAAgBC,CAAc,EAAIC,GACvCV,EAAQ,SACV,EACM,CAACW,EAAmBC,CAAiB,EACzCC,GAAuBZ,CAAe,EAExC,QAAQ,eACN,IAAIL,CAAM,OAAOM,CAAe,OAAOG,CAAqB,QAAQG,CAAc,OAAOG,CAAiB,GAC1GR,EACAG,EACAG,EACAG,CACF,EAEA,GAAM,CAACE,EAAgBC,EAAc,EAAIC,EAAmB,SAAS,EAC/D,CAACC,GAAgBC,EAAc,EAAIC,EACvCnB,EAAQ,SAAW,SACrB,EACM,CAACoB,GAAmBC,EAAiB,EACzCL,EAAmB,YAAY,EAC3B,CAACM,GAAmBC,EAAiB,EAAIJ,EAC7CnB,EAAQ,YAAc,SACxB,EACM,CAACwB,GAAmBC,EAAiB,EACzCT,EAAmB,YAAY,EAC3B,CAACU,GAAmBC,EAAiB,EAAIR,EAC7CnB,EAAQ,YAAc,SACxB,EAEA,QAAQ,IACN,KAAKc,CAAc,MAAMG,EAAc,GACvCF,GACAG,EACF,EACA,QAAQ,IACN,KAAKE,EAAiB,MAAME,EAAiB,GAC7CD,GACAE,EACF,EACA,QAAQ,IACN,KAAKC,EAAiB,MAAME,EAAiB,GAC7CD,GACAE,EACF,EACA,QAAQ,MAAM3B,EAAQ,UAAU,EAChC,QAAQ,SAAS,CACnB,EACA,KAAM,IAAIH,IAAoB,CAC5B,QAAQ,KAAK,IAAID,CAAM,IAAK,GAAGC,CAAI,CACrC,EACA,QAAS,CAAC+B,KAAoB/B,IAAoB,CAE9C,OAMF,GAAI,CAACgC,EAAmB,CACtB9B,EAAY,QAAQ+B,CAAgB,EAAI,GACxC,IAAMC,EAAU,IAAInC,CAAM,KAAKkC,CAAgB,GAE/C,QAAQ,KAAKC,EAAS,GAAGlC,CAAI,EAE7B,GAAI,CAMF,MAAM,IAAI,MAAMkC,CAAO,CACzB,MAAgB,CAEhB,CACF,CACF,EACA,MAAO,IAAIlC,IAAoB,CAC7B,QAAQ,MAAM,IAAID,CAAM,IAAK,GAAGC,CAAI,CACtC,CACF,CACF,CAEO,IAAME,EAAoD,CAC/D,QAAS,CAAC,CACZ,EAEA,SAASiC,GAAgBC,EAAmB,CAC1C,OAAO,IAAI,KAAKA,CAAS,EAAE,mBAAmB,QAAS,CACrD,OAAQ,GACR,KAAM,UACN,OAAQ,UACR,OAAQ,SACV,CAAC,CACH,CAEA,SAAS7B,GAAwB8B,EAAiC,CAChE,MAAO,CACLA,EACA,8FACF,CACF,CAEA,SAAS3B,GAA8B2B,EAAiC,CACtE,MAAO,CAACA,EAAO,UAAUC,GAAoBD,CAAK,CAAC,qBAAqB,CAC1E,CAEA,SAASC,GAAoBC,EAAqB,CAKhD,OAJqBA,EAAY,kBAAkB,EAAE,WAAW,MAAM,EAClE,aACAA,EAEkB,CACpB,IAAK,aACH,MAAO,UACT,QACE,MAAO,SACX,CACF,CAEA,SAAS1B,GAAuBwB,EAAiC,CAC/D,MAAO,CAACF,GAAgBE,CAAK,EAAG,mCAAmC,CACrE,CAEA,SAASlB,EAAmBkB,EAAiC,CAC3D,MAAO,CAACA,EAAO,kCAAkC,CACnD,CAEA,SAASf,EAAmBe,EAAiC,CAC3D,MAAO,CACLA,EACA,qKACF,CACF,CAEA,SAASrB,GACPZ,EACkB,CAClB,OAAQA,EAAiB,CACvB,KAAKoC,EAAgB,QACnB,MAAO,CAAC,GAAI,EAAE,EAChB,KAAKA,EAAgB,OACnB,MAAO,CACL,SACA,+GACF,EACF,KAAKA,EAAgB,QACrB,KAAKA,EAAgB,UACnB,MAAO,CACL,UACA,+GACF,EACF,QACE,MAAO,CACL,UACA,+GACF,CACJ,CACF,CC3LO,SAASC,EAA6BC,EAA6B,CACxE,GACE,OAAO,WAAW,OAAW,KAC7B,OAAO,WAAW,OAAO,YAAe,WAExC,GAAI,CACF,MAAO,GAAGA,CAAM,IAAI,OAAO,WAAW,CAAC,EACzC,MAAQ,CAER,CAEF,MAAO,GAAGA,CAAM,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC,EAC7D,CCQO,IAAMC,EAAN,KAAqB,CAClB,wBACA,QACA,aACA,SACA,YAER,YAAYC,EAKT,CACD,KAAK,SAAWA,EAAQ,QACxB,KAAK,YAAcA,EAAQ,WAC3B,KAAK,QAAUA,EAAQ,OACvB,KAAK,wBACHA,EAAQ,wBAA0BC,EAAgB,QACpD,KAAK,aAAe,KAAK,0BAA0B,CACrD,CAEA,MAAa,CACX,IAAMC,EAAa,KAAK,SAAS,QAAQ,KAAK,WAAW,EAEzD,GAAI,CAACA,EAAY,CACf,KAAK,aAAe,KAAK,0BAA0B,EACnD,KAAK,kBAAkB,EACvB,MACF,CAEA,GAAI,CACF,IAAMC,EAAa,KAAK,MAAMD,CAAU,EAExC,KAAK,aAAe,CAClB,UAAWC,EAAW,WAAa,KAAK,mBAAmB,EAC3D,UAAWA,EAAW,WAAa,KAAK,mBAAmB,EAC3D,OAAQA,EAAW,QAAU,KAC7B,YAAaA,EAAW,aAAe,KACvC,gBAAiBC,GAAuBD,EAAW,eAAe,EAC9DA,EAAW,gBACX,KAAK,uBACX,CACF,MAAgB,CACd,KAAK,QAAQ,QACX,uDACF,EACA,KAAK,aAAe,KAAK,0BAA0B,CACrD,CAEA,KAAK,kBAAkB,CACzB,CAEA,cAA0B,CACxB,OAAO,KAAK,aAAa,SAC3B,CAEA,cAA0B,CACxB,OAAO,KAAK,aAAa,SAC3B,CAEA,WAA2B,CACzB,OAAO,KAAK,aAAa,MAC3B,CAEA,gBAAgC,CAC9B,OAAO,KAAK,aAAa,WAC3B,CAEA,oBAA0C,CACxC,OAAO,KAAK,aAAa,eAC3B,CAEA,UAAUE,EAA6B,CACrC,KAAK,aAAa,OAASA,EAC3B,KAAK,kBAAkB,CACzB,CAEA,mBAAmBC,EAAoC,CACrD,KAAK,aAAa,gBAAkBA,EACpC,KAAK,kBAAkB,CACzB,CAEA,kBAAkBC,EAAyB,CACzC,KAAK,aAAa,YAAcA,EAChC,KAAK,kBAAkB,CACzB,CAEA,sBAAgC,CAG9B,OAFoB,KAAK,oBAAoB,GAG3C,KAAK,cAAc,EACnB,KAAK,kBAAkB,EAChB,IAGF,EACT,CAEA,MAAM,CACJ,eAAAC,EAAiB,GACjB,eAAAC,EAAiB,GACjB,qBAAAC,EAAuB,EACzB,EAII,CAAC,EAAS,CACRF,IACF,KAAK,aAAa,UAAY,KAAK,mBAAmB,GAGpDC,IACF,KAAK,aAAa,UAAY,KAAK,mBAAmB,GAGpDC,IACF,KAAK,aAAa,gBAAkB,KAAK,yBAG3C,KAAK,aAAa,OAAS,KAC3B,KAAK,aAAa,YAAc,KAChC,KAAK,kBAAkB,CACzB,CAEQ,2BAAyC,CAC/C,MAAO,CACL,UAAW,KAAK,mBAAmB,EACnC,UAAW,KAAK,mBAAmB,EACnC,OAAQ,KACR,YAAa,KACb,gBAAiB,KAAK,uBACxB,CACF,CAEQ,oBAAgC,CACtC,OAAOC,EAAWC,CAAiB,CACrC,CAEQ,oBAAgC,CACtC,OAAOD,EAAWE,CAAiB,CACrC,CAEQ,qBAA+B,CACrC,GAAM,CAAE,YAAAC,CAAY,EAAI,KAAK,aAE7B,GAAI,CAACA,EACH,MAAO,GAGT,IAAMC,EAAM,IAAI,KAAK,EAAE,QAAQ,EACzBC,EAAgB,IAAI,KAAKF,CAAW,EAAE,QAAQ,EAGpD,OAF2BC,EAAMC,EAELC,CAC9B,CAEQ,eAAsB,CAC5B,KAAK,aAAa,UAAY,KAAK,mBAAmB,EACtD,KAAK,aAAa,YAAc,IAClC,CAEQ,mBAA0B,CAChC,GAAI,CACF,KAAK,SAAS,QACZ,KAAK,YACL,KAAK,UAAU,KAAK,YAAY,CAClC,CACF,MAAgB,CACd,KAAK,QAAQ,QAAQ,4CAA4C,CACnE,CACF,CACF,EAEA,SAASb,GAAuBc,EAA8C,CAC5E,OACE,OAAOA,GAAU,UACjB,OAAO,OAAOjB,CAAe,EAAE,SAASiB,CAA4B,CAExE,CCtLA,SAASC,EACPC,EACAC,EACAC,EACM,CACN,QAAWC,KAAOD,EAAM,CACtB,IAAME,EAAQH,EAAY,QAAQE,CAAG,EACjCC,IAAU,OACZJ,EAAU,QAAQG,EAAKC,CAAK,EAC5BH,EAAY,WAAWE,CAAG,EAE9B,CACF,CAEA,IAAME,EAAN,KAAwC,CAC9B,MAAgC,CAAC,EACzC,QAAQF,EAA4B,CAClC,OAAO,KAAK,MAAMA,CAAG,GAAK,IAC5B,CACA,QAAQA,EAAaC,EAAe,CAClC,KAAK,MAAMD,CAAG,EAAIC,CACpB,CACA,WAAWD,EAAa,CACtB,OAAO,KAAK,MAAMA,CAAG,CACvB,CACA,QAAQF,EAAyBC,EAAgB,CAC/CH,EAAY,KAAME,EAAaC,CAAI,CACrC,CACF,EAEMI,EAAN,KAAwC,CACtC,QAAQH,EAA4B,CAClC,OAAOI,EACL,CAAC,CAAE,OAAAC,CAAO,IAAM,CACd,IAAMC,EAAQD,EAAO,SAAS,OAAO,MACnC,IAAI,OAAO,QAAUL,EAAM,UAAU,CACvC,EACA,OAAOM,EAAQ,mBAAmBA,EAAM,CAAC,CAAC,EAAI,IAChD,EACA,IAAM,IACR,CACF,CACA,QAAQN,EAAaC,EAAe,CAClCG,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjCA,EAAO,SAAS,OAAS,GAAGL,CAAG,IAAI,mBAAmBC,CAAK,CAAC,WAC9D,CAAC,CACH,CACA,WAAWD,EAAa,CACtBI,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjCA,EAAO,SAAS,OAAS,GAAGL,CAAG,uBACjC,CAAC,CACH,CACA,QAAQF,EAAyBC,EAAgB,CAC/CH,EAAY,KAAME,EAAaC,CAAI,CACrC,CACF,EAEMQ,EAAN,KAA4C,CAC1C,YAAoBC,EAA4C,CAA5C,aAAAA,CAA6C,CACjE,QAAQR,EAA4B,CAClC,OAAOI,EACL,CAAC,CAAE,OAAAC,CAAO,IAAM,CACd,GAAI,CACF,OAAOA,EAAO,KAAK,OAAO,EAAE,QAAQL,CAAG,CACzC,MAAQ,CACN,OAAO,IACT,CACF,EACA,IAAM,IACR,CACF,CACA,QAAQA,EAAaC,EAAe,CAClCG,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjC,GAAI,CACFA,EAAO,KAAK,OAAO,EAAE,QAAQL,EAAKC,CAAK,CACzC,MAAQ,CAER,CACF,CAAC,CACH,CACA,WAAWD,EAAa,CACtBI,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjC,GAAI,CACFA,EAAO,KAAK,OAAO,EAAE,WAAWL,CAAG,CACrC,MAAQ,CAER,CACF,CAAC,CACH,CACA,QAAQF,EAAyBC,EAAgB,CAC/CH,EAAY,KAAME,EAAaC,CAAI,CACrC,CACF,EAEMU,EAAN,KAAiD,CACvC,WAAa,IAAIF,EAAgB,cAAc,EAC/C,YAAc,IAAIJ,EAC1B,QAAQH,EAA4B,CAClC,OAAO,KAAK,WAAW,QAAQA,CAAG,GAAK,KAAK,YAAY,QAAQA,CAAG,CACrE,CACA,QAAQA,EAAaC,EAAe,CAClC,KAAK,WAAW,QAAQD,EAAKC,CAAK,EAClC,KAAK,YAAY,QAAQD,EAAKC,CAAK,CACrC,CACA,WAAWD,EAAa,CACtB,KAAK,WAAW,WAAWA,CAAG,EAC9B,KAAK,YAAY,WAAWA,CAAG,CACjC,CACA,QAAQF,EAAyBC,EAAgB,CAE/C,QAAWC,KAAOD,EAAM,CACtB,IAAME,EAAQH,EAAY,QAAQE,CAAG,EACjCC,IAAU,OACZ,KAAK,WAAW,QAAQD,EAAKC,CAAK,EAClC,KAAK,YAAY,QAAQD,EAAKC,CAAK,EAEvC,CAEA,QAAWD,KAAOD,EAChBD,EAAY,WAAWE,CAAG,CAE9B,CACF,EAEA,SAASU,EACPC,EACA,CACA,OAAOP,EACL,CAAC,CAAE,OAAAC,CAAO,IAAM,CACd,GAAI,CACF,GAAIM,IAAgB,SAAU,CAC5BN,EAAO,SAAS,OAAS,GAAGO,CAAgB,KAC5C,IAAMC,EACJR,EAAO,SAAS,OAAO,QAAQ,GAAGO,CAAgB,GAAG,IAAM,GAC7D,OAAAP,EAAO,SAAS,OAAS,GAAGO,CAAgB,eACrCC,CACT,KACE,QAAAR,EAAOM,CAAW,EAAE,QAAQC,EAAkB,GAAG,EACjDP,EAAOM,CAAW,EAAE,WAAWC,CAAgB,EACxC,EAEX,MAAQ,CACN,MAAO,EACT,CACF,EACA,IAAM,EACR,CACF,CAEO,SAASE,EACdC,EACAC,EACY,CACZ,GAAM,CAAE,WAAAC,CAAW,EAAID,EAEvB,OAAQD,EAAM,CACZ,IAAK,eACH,OAAIL,EAAmB,cAAc,EAC5B,IAAIH,EAAgB,cAAc,GAE3CU,EACE,kEACF,EACOH,EAAc,sBAAuBE,CAAM,GAGpD,IAAK,sBAAuB,CAC1B,IAAME,EAAwBR,EAAmB,cAAc,EACzDS,EAAkBT,EAAmB,QAAQ,EAEnD,OAAIQ,GAAyBC,EACpB,IAAIV,EACFU,GACTF,EACE,kEACF,EACO,IAAId,GACFe,GACTD,EAAW,qDAAqD,EACzD,IAAIV,EAAgB,cAAc,IAEzCU,EACE,oEACF,EACO,IAAIf,EAEf,CAEA,IAAK,iBACH,OAAIQ,EAAmB,gBAAgB,EAC9B,IAAIH,EAAgB,gBAAgB,GAE7CU,EAAW,uDAAuD,EAC3D,IAAIf,GAGb,IAAK,SACH,OAAIQ,EAAmB,QAAQ,EACtB,IAAIP,GAEbc,EAAW,+CAA+C,EACnD,IAAIf,GAGb,IAAK,SACH,OAAO,IAAIA,EAGb,QACE,MAAM,IAAI,MACR,0BAA0Ba,CAAI,wFAChC,CAEJ,CACF,CClOA,IAAMK,GAA0B,CAC9B,GAAGC,EACH,GAAGC,CACL,EACG,IAAIC,GAAM,MAAMA,CAAE,GAAG,EACrB,KAAK;AAAA,CAAI,EACNC,EAA0B;AAAA,EAAkCJ,EAAuB,GAElF,SAASK,EAAeC,EAAsB,CACnD,GAAI,CAACA,GAAUA,EAAO,KAAK,IAAM,GAC/B,MAAM,IAAI,MAAM,qDAAqD,EAOvE,GAJiCL,EAAkB,KACjDM,GAAaD,EAAO,YAAY,IAAMC,EAAU,YAAY,CAC9D,EAGE,MAAM,IAAI,MACR,YAAYD,CAAM;AAAA;AAAA,EAChBF,CACJ,EAKF,GAF+BF,EAAiC,IAAII,CAAM,EAGxE,MAAM,IAAI,MACR,YAAYA,CAAM;AAAA;AAAA,EAChBF,CACJ,CAEJ,CCuCO,IAAMI,EAAN,KAAiB,CACd,QACA,oBACA,QACA,YACA,eAAiB,GACjB,SACA,QAAUC,EAAa,YAAY,EACnC,UACA,gBACA,SACA,YAER,aAAc,CACZ,KAAK,SAAW,KAChB,KAAK,UAAY,KACjB,KAAK,YAAc,IAAIC,EAAWC,CAAoB,CACxD,CAEA,KAAKC,EAAgBC,EAA2B,CAAC,EAAG,CAClDC,EAAUF,EAAQ,iBAAiB,EACnC,KAAK,QAAUA,EACf,KAAK,QAAUC,EACf,KAAK,YAAcE,EACjBH,EACA,KAAK,QAAQ,aAAeI,CAC9B,EACA,KAAK,UAAYC,EACf,CAAC,CAAE,OAAAC,CAAO,IAAMA,EAAO,SAAS,UAAY,KAC5C,IAAM,IACR,EACA,KAAK,SAAWD,EACd,CAAC,CAAE,OAAAC,CAAO,IAAMA,EAAO,SAAS,MAAQ,KACxC,IAAM,IACR,EACA,IAAMC,EAA2BN,EAAO,aAAeO,EACvD,YAAK,SAAWC,EAAcF,EAAa,CACzC,WAAYG,GAAW,KAAK,QAAQ,KAAKA,CAAO,CAClD,CAAC,EAED,KAAK,gBAAkB,IAAIC,EAAe,CACxC,QAAS,KAAK,SACd,WAAY,KAAK,YACjB,OAAQ,KAAK,QACb,uBAAwBV,EAAO,iBAAmBW,EAAgB,OACpE,CAAC,EACD,KAAK,gBAAgB,KAAK,EAE1B,KAAK,eAAiB,GAElB,KAAK,QAAQ,OACf,KAAK,QAAQ,UAAU,EAGzB,KAAK,yBAAyBX,EAAO,aAAe,EAAI,EAEjD,IAAM,CACX,KAAK,sBAAsB,CAC7B,CACF,CAEA,UAAUY,EAAoC,CAa5C,GAZAX,EACE,KAAK,eACL,gEACF,EAGEW,EAAQ,cAAgB,QACxBA,EAAQ,cAAgB,KAAK,QAAQ,aAErC,KAAK,yBAAyBA,EAAQ,WAAW,EAIjDA,EAAQ,cAAgB,QACxBA,EAAQ,cAAgB,KAAK,QAAQ,YACrC,CACA,IAAMC,EAAkB,KAAK,SAC7B,KAAK,SAAWL,EAAcI,EAAQ,YAAa,CACjD,WAAYH,GAAW,KAAK,QAAQ,KAAKA,CAAO,CAClD,CAAC,EACD,KAAK,SAAS,QAAQI,EAAiB,CAAC,KAAK,WAAW,CAAC,CAC3D,CAEA,IAAMC,EAAyB,KAAK,gBAAgB,mBAAmB,EACvE,GACEF,EAAQ,kBAAoB,QAC5BA,EAAQ,kBAAoBE,EAI5B,GAFA,KAAK,gBAAgB,mBAAmBF,EAAQ,eAAe,EAG7DE,IAA2BH,EAAgB,SAC3CC,EAAQ,kBAAoBD,EAAgB,QAC5C,CACA,IAAMI,EAAe,KAAK,YAAY,MAAM,EACxCA,EAAa,OAAS,GACxBA,EAAa,QAAQC,GAAS,CAC5B,KAAK,cAAcA,EAAM,UAAWA,EAAM,QAASA,EAAM,OAAO,CAClE,CAAC,CAEL,MAAWJ,EAAQ,kBAAoBD,EAAgB,QACrD,KAAK,YAAY,MAAM,EAI3B,KAAK,QAAU,CAAE,GAAG,KAAK,QAAS,GAAGC,CAAQ,CAC/C,CAEQ,yBAAyBK,EAA4B,CAG3D,GAFA,KAAK,sBAAsB,EAEvBA,EAAmB,CACjB,KAAK,UACP,KAAK,KAAK,KAAK,QAAQ,EAGzB,IAAMC,EAAkB,KAAK,iBAAiB,KAAK,IAAI,EACjDC,EAAa,YAAYD,EAAiBE,CAAwB,EAExEhB,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjCA,EAAO,iBAAiB,WAAYa,CAAe,EACnDb,EAAO,iBAAiB,aAAca,CAAe,CACvD,CAAC,EAED,KAAK,oBAAsB,IAAM,CAC/B,cAAcC,CAAU,EACxBf,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjCA,EAAO,oBAAoB,WAAYa,CAAe,EACtDb,EAAO,oBAAoB,aAAca,CAAe,CAC1D,CAAC,CACH,CACF,MACE,KAAK,oBAAsB,MAE/B,CAEA,SAASG,EAAgBC,EAAqB,CAAC,EAAG,CAChDrB,EACE,KAAK,eACL,sEACF,EAEA,GAAI,CACFsB,EAAeF,CAAM,CACvB,OAASG,EAAO,CACd,MAAM,IAAI,MAAM,gBAAgBA,EAAM,OAAO,EAAE,CACjD,CAEA,KAAK,gBAAgB,UAAUH,CAAM,EACrC,IAAMI,EAAU,KAAK,iBAAiB,EACtC,KAAK,cACH,WACA,CACE,YAAaA,EAAQ,YACrB,OAAAH,EACA,QAASD,EACT,WAAYI,EAAQ,UACtB,EACAA,CACF,CACF,CAEA,aAAaH,EAAoB,CAC/B,IAAMD,EAAS,KAAK,gBAAgB,UAAU,EAC9CpB,EACEoB,EACA,iEACF,EAEA,IAAMI,EAAU,KAAK,iBAAiB,EACtC,KAAK,cACH,WACA,CACE,YAAaA,EAAQ,YACrB,OAAAH,EACA,QAASD,EACT,WAAYI,EAAQ,UACtB,EACAA,CACF,CACF,CAEA,MAAM,CACJ,eAAAC,EAAiB,GACjB,eAAAC,EAAiB,EACnB,EAGI,CAAC,EAAG,CACN1B,EACE,KAAK,eACL,8DACF,EAEA,KAAK,gBAAgB,MAAM,CAAE,eAAAyB,EAAgB,eAAAC,CAAe,CAAC,CAC/D,CAEA,KAAKC,EAAa,CAChB3B,EACE,KAAK,eACL,wEACF,EAEA,IAAM4B,EAAY,IAAI,IAAID,CAAG,EACvBE,EAAmB,GAAGD,EAAU,MAAM,GAAGA,EAAU,QAAQ,GACjE,KAAK,MAAME,EAAgB,CACzB,CAACC,CAAY,EAAGF,EAChB,CAACG,CAAiB,EAAGC,EAAY,EACjC,CAACC,CAAgB,EAAG,KAAK,UACzB,GAAG,OAAO,YAAYN,EAAU,YAAY,CAC9C,CAAC,CACH,CAEA,MAAMb,EAAeoB,EAA8B,CAAC,EAAG,CACrDnC,EACE,KAAK,eACL,oEACF,EAEA,KAAK,gBAAgB,qBAAqB,EAC1C,IAAMoC,EAAY,IAAI,KAAK,EAAE,YAAY,EACzC,KAAK,gBAAgB,kBAAkBA,CAAS,EAEhD,IAAMZ,EAAU,KAAK,iBAAiB,EAChCa,EAAwB,CAC5B,UAAAD,EACA,MAAArB,EACA,YAAaS,EAAQ,YACrB,QAASA,EAAQ,QACjB,WAAYA,EAAQ,WACpB,WAAYA,EAAQ,WACpB,WAAY,CACV,CAACc,CAAY,EAAG,4BAChB,CAACC,CAAoB,EAAG,QACxB,CAACC,CAAgB,EAAG,KAAK,QAAQ,QAGjC,GAAGL,CACL,CACF,EAIA,GAFA,KAAK,cAAc,QAASE,EAASb,CAAO,EAExC,KAAK,QAAQ,MAAO,CACtB,IAAMiB,EAAkB,KAAK,gBAAgB,mBAAmB,EAChE,KAAK,QAAQ,SAASJ,EAAS,CAAE,gBAAAI,CAAgB,CAAC,CACpD,CACF,CAEA,oBAA0C,CACxC,OAAO,KAAK,gBAAgB,mBAAmB,CACjD,CAEQ,kBAAmB,CACzBtC,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjC,GAAI,CAAC,KAAK,QAAQ,YAChB,OAGF,IAAMsC,EAAatC,EAAO,SAAS,KAC/BsC,IAAe,KAAK,WACtB,KAAK,KAAKA,CAAU,EACpB,KAAK,UAAY,KAAK,SACtB,KAAK,SAAWA,EAEpB,CAAC,CACH,CAEQ,kBAAiC,CACvC,MAAO,CACL,YAAa,KAAK,QAAQ,aAAexC,EACzC,QAAS,KAAK,gBAAgB,UAAU,EACxC,WAAY,KAAK,gBAAgB,aAAa,EAC9C,WAAY,KAAK,gBAAgB,aAAa,CAChD,CACF,CAEQ,cACNyC,EACAN,EACAb,EACA,CAGA,OAFwB,KAAK,gBAAgB,mBAAmB,EAEvC,CACvB,KAAKd,EAAgB,QACnB,KAAK,SAAS,IAAIiC,CAAS,GAAIN,CAAO,EACtC,MACF,KAAK3B,EAAgB,QACrB,KAAKA,EAAgB,UACnB,KAAK,YAAY,QAAQiC,EAAWN,EAASb,CAAO,EACpD,MACF,KAAKd,EAAgB,OAEnB,KACJ,CACF,CAEQ,SAASkC,EAAcC,EAAqB,CAClD7C,EAAU,KAAK,QAAS,iBAAiB,EACzCA,EAAU,KAAK,QAAS,uBAAuB,EAE/C,IAAM2B,EAAM,GAAG,KAAK,QAAQ,SAAWmB,CAAgB,GAAGF,CAAI,GACxDP,EAAU,KAAK,UAAUQ,CAAI,EAGnC,GAAI,OAAO,UAAc,KAAe,UAAU,WAAY,CAC5D,IAAME,EAAY,GAAGpB,CAAG,WAAW,mBAAmB,KAAK,OAAO,CAAC,GAC7DqB,EAAO,IAAI,KAAK,CAACX,CAAO,EAAG,CAAE,KAAM,kBAAmB,CAAC,EAC7D,UAAU,WAAWU,EAAWC,CAAI,CACtC,MACE,MAAMrB,EAAK,CACT,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,cAAe,UAAU,KAAK,OAAO,EACvC,EACA,KAAMU,CACR,CAAC,CAEL,CACF,EClYO,IAAMY,EAAa,IAAIC,EAE9BC,EAAmB,CAAC,CAAE,OAAAC,CAAO,IAAM,CACjC,IAAMC,EAAOD,EAAO,WACpB,GAAIC,GAAQ,MAAM,QAAQA,CAAI,EAC5B,QAAWC,KAAQD,EAAM,CACvB,IAAME,EAASD,EAAK,CAAC,EACfE,EAAOF,EAAK,MAAM,CAAC,EACxBL,EAAWM,CAA0B,EAAU,GAAGC,CAAI,CACzD,CAGFJ,EAAO,WAAaH,CACtB,CAAC","names":["createKeyBuilder","prefix","separator","parts","DEFAULT_BASE_URL","DEFAULT_ENVIRONMENT","DEFAULT_PERSISTENCE","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_EVENT_QUEUE_SIZE","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","EventQueue","queueMaxSize","eventType","payload","context","events","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","invariant","condition","message","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabelLabel","userLabelStyle","createLabelElement","userValueLabel","userValueStyle","createValueElement","visitorLabelLabel","visitorLabelStyle","visitorValueLabel","visitorValueStyle","sessionLabelLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","value","getEnvironmentColor","environment","TrackingConsent","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetVisitorId","resetSessionId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","lastEventAt","now","lastEventTime","SESSION_EXPIRATION_TIME_MS","value","migrateKeys","toStorage","fromStorage","keys","key","value","MemoryStore","CookieStore","safelyRunOnBrowser","window","match","WebStorageStore","storage","LocalPlusCookieStore","testStorageSupport","storageType","STORAGE_KEY_TEST","supported","selectStorage","type","params","onFallback","localStorageSupported","cookieSupported","reservedIdentifiersList","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","id","reservedIdentifiersInfo","validateUserId","userId","blockedId","Altertable","createLogger","EventQueue","MAX_EVENT_QUEUE_SIZE","apiKey","config","invariant","keyBuilder","DEFAULT_ENVIRONMENT","safelyRunOnBrowser","window","persistence","DEFAULT_PERSISTENCE","selectStorage","message","SessionManager","TrackingConsent","updates","previousStorage","currentTrackingConsent","queuedEvents","event","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","resetVisitorId","resetSessionId","url","parsedUrl","urlWithoutSearch","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","getViewport","PROPERTY_REFERER","properties","timestamp","payload","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","trackingConsent","currentUrl","eventType","path","body","DEFAULT_BASE_URL","beaconUrl","blob","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}
1
+ {"version":3,"sources":["../src/lib/createKeyBuilder.ts","../src/constants.ts","../src/lib/eventQueue.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/getViewport.ts","../src/lib/invariant.ts","../src/lib/logger.ts","../src/lib/generateId.ts","../src/lib/sessionManager.ts","../src/lib/storage.ts","../src/lib/validateUserId.ts","../src/core.ts","../src/index.ts"],"sourcesContent":["export function createKeyBuilder(prefix: string, separator: string) {\n return (...parts: string[]) => {\n return [prefix, ...parts].join(separator);\n };\n}\n","import { createKeyBuilder } from './lib/createKeyBuilder';\n\nexport const DEFAULT_BASE_URL = 'https://api.altertable.ai';\nexport const DEFAULT_ENVIRONMENT = 'production';\nexport const DEFAULT_PERSISTENCE = 'localStorage+cookie';\n\nconst STORAGE_KEY_PREFIX = 'atbl';\nexport const keyBuilder = createKeyBuilder(STORAGE_KEY_PREFIX, '.');\nexport const STORAGE_KEY_TEST = keyBuilder('check');\n\nexport const PREFIX_SESSION_ID = 'session';\nexport const PREFIX_VISITOR_ID = 'visitor';\n\nconst MINUTE_IN_MS = 1000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_EVENT_QUEUE_SIZE = 1000;\n\nexport const EVENT_PAGEVIEW = '$pageview';\n\nexport const PROPERTY_LIB = '$lib';\nexport const PROPERTY_LIB_VERSION = '$lib_version';\nexport const PROPERTY_REFERER = '$referer';\nexport const PROPERTY_RELEASE = '$release';\nexport const PROPERTY_URL = '$url';\nexport const PROPERTY_VIEWPORT = '$viewport';\n\nexport const TrackingConsent = {\n DENIED: 'denied',\n DISMISSED: 'dismissed',\n GRANTED: 'granted',\n PENDING: 'pending',\n} as const;\n\nexport type TrackingConsentType =\n (typeof TrackingConsent)[keyof typeof TrackingConsent];\n\nexport const RESERVED_USER_IDS = [\n 'anonymous_id',\n 'anonymous',\n 'distinct_id',\n 'distinctid',\n 'false',\n 'guest',\n 'id',\n 'not_authenticated',\n 'true',\n 'undefined',\n 'user_id',\n 'user',\n 'visitor_id',\n 'visitor',\n];\nexport const RESERVED_USER_IDS_CASE_SENSITIVE = new Set([\n '[object Object]',\n '0',\n 'NaN',\n 'none',\n 'None',\n 'null',\n]);\n","import type { EventContext, EventType } from '../types';\n\ntype QueuedEvent<TPayload> = {\n eventType: EventType;\n payload: TPayload;\n sentAt: Date;\n context: EventContext;\n};\n\nexport class EventQueue<TPayload> {\n private _queue: QueuedEvent<TPayload>[] = [];\n private _queueMaxSize: number;\n\n constructor(queueMaxSize: number) {\n this._queueMaxSize = queueMaxSize;\n }\n\n enqueue(\n eventType: 'track' | 'identify',\n payload: TPayload,\n context: EventContext\n ): void {\n if (this._queue.length >= this._queueMaxSize) {\n // Remove oldest event to make room for new one\n this._queue.shift();\n }\n this._queue.push({\n eventType,\n payload,\n context,\n sentAt: new Date(),\n });\n }\n\n flush(): Array<QueuedEvent<TPayload>> {\n const events = [...this._queue];\n this._queue = [];\n return events;\n }\n\n clear(): void {\n this._queue = [];\n }\n\n getSize(): number {\n return this._queue.length;\n }\n}\n","/* eslint-disable no-restricted-globals */\n\n/** Runs code on browser environments safely. */\nexport function safelyRunOnBrowser<TReturn>(\n callback: (params: { window: typeof window }) => TReturn,\n /** Fallback to run on server environments. */\n fallback: () => TReturn = () => undefined as unknown as TReturn\n): TReturn {\n if (typeof window === 'undefined') {\n return fallback();\n }\n\n return callback({ window });\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport function getViewport(): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","/**\n * Throws an error if the condition is not met.\n *\n * The error is exhaustive in development, and becomes generic in production.\n *\n * This is used to make development a better experience to provide guidance as\n * to where the error comes from.\n */\nexport function invariant(\n condition: unknown,\n message: string | (() => string)\n): asserts condition {\n if (condition) {\n return;\n }\n\n if (__DEV__) {\n throw new Error(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n }\n\n throw new Error('Invariant failed');\n}\n","/* eslint-disable no-console */\n\nimport { TrackingConsent, TrackingConsentType } from '../constants';\nimport { EventPayload } from '../types';\n\nexport type Logger = ReturnType<typeof createLogger>;\n\nexport function createLogger(prefix: string) {\n return {\n log: (...args: unknown[]) => {\n console.log(`[${prefix}]`, ...args);\n },\n logHeader: () => {\n const header = `Altertable v${__LIB_VERSION__} %c• Debug mode enabled`;\n const hasAlreadyPrinted = loggerCache.current[header];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[header] = true;\n console.log(header, 'color: #64748b;');\n }\n },\n logEvent: (\n payload: EventPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event\n );\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [timestampLabel, timestampStyle] = createTimestampElement(\n payload.timestamp\n );\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c [${environmentBadgeLabel}] %c(${timestampLabel}) %c${consentBadgeLabel}`,\n eventBadgeStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabelLabel, userLabelStyle] = createLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.user_id ?? 'Not set'\n );\n const [visitorLabelLabel, visitorLabelStyle] =\n createLabelElement('Visitor ID');\n const [visitorValueLabel, visitorValueStyle] = createValueElement(\n payload.visitor_id ?? 'Not set'\n );\n const [sessionLabelLabel, sessionLabelStyle] =\n createLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabelLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${visitorLabelLabel} %c${visitorValueLabel}`,\n visitorLabelStyle,\n visitorValueStyle\n );\n console.log(\n `%c${sessionLabelLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n warn: (...args: unknown[]) => {\n console.warn(`[${prefix}]`, ...args);\n },\n warnDev: (message: string, ...args: unknown[]) => {\n if (!__DEV__) {\n return;\n }\n\n const sanitizedMessage = message.trim();\n const hasAlreadyPrinted = loggerCache.current[sanitizedMessage];\n\n if (!hasAlreadyPrinted) {\n loggerCache.current[sanitizedMessage] = true;\n const warning = `[${prefix}] ${sanitizedMessage}`;\n\n console.warn(warning, ...args);\n\n try {\n // Welcome to debugging Altertable.\n //\n // This error was thrown as a convenience so that you can find the source\n // of the warning that appears in the console by enabling \"Pause on exceptions\"\n // in your debugger.\n throw new Error(warning);\n } catch (error) {\n // Do nothing\n }\n }\n },\n error: (...args: unknown[]) => {\n console.error(`[${prefix}]`, ...args);\n },\n };\n}\n\nexport const loggerCache: { current: Record<string, boolean> } = {\n current: {},\n};\n\nfunction formatEventTime(timestamp: string) {\n return new Date(timestamp).toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction createEventBadgeElement(value: string): [string, string] {\n return [\n value,\n 'background: #1e293b; color: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 400;',\n ];\n}\n\nfunction createEnvironmentBadgeElement(value: string): [string, string] {\n return [value, `color: ${getEnvironmentColor(value)}; font-weight: 400;`];\n}\n\nfunction getEnvironmentColor(environment: string) {\n const formattedEnv = environment.toLocaleLowerCase().startsWith('prod')\n ? 'production'\n : environment;\n\n switch (formattedEnv) {\n case 'production':\n return '#ef4444';\n default:\n return '#3b82f6';\n }\n}\n\nfunction createTimestampElement(value: string): [string, string] {\n return [formatEventTime(value), 'color: #64748b; font-weight: 400;'];\n}\n\nfunction createLabelElement(value: string): [string, string] {\n return [value, 'color: #64748b; font-size: 11px;'];\n}\n\nfunction createValueElement(value: string): [string, string] {\n return [\n value,\n 'background: #f8fafc; color: #1e293b; padding: 2px 8px; border: 1px solid #e2e8f0; border-radius: 6px; font-family: \"SF Mono\", \"Monaco\", monospace; font-size: 11px;',\n ];\n}\n\nfunction getConsentBadgeElement(\n trackingConsent: TrackingConsentType\n): [string, string] {\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n return ['', ''];\n case TrackingConsent.DENIED:\n return [\n 'DENIED',\n 'background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n return [\n 'PENDING',\n 'background: #f59e0b; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n default:\n return [\n 'UNKNOWN',\n 'background: #6b7280; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;',\n ];\n }\n}\n","export function generateId<T extends string>(prefix: T): `${T}-${string}` {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n try {\n return `${prefix}-${crypto.randomUUID()}`;\n } catch {\n // Continue with Math.random() fallback.\n }\n }\n return `${prefix}-${Math.random().toString(36).substring(2)}`;\n}\n","import {\n PREFIX_SESSION_ID,\n PREFIX_VISITOR_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\nimport type { UserId, VisitorId, SessionId } from '../types';\n\ntype SessionData = {\n visitorId: VisitorId;\n sessionId: SessionId;\n userId: UserId | null;\n lastEventAt: string | null;\n trackingConsent: TrackingConsentType;\n};\n\nexport class SessionManager {\n private _defaultTrackingConsent: TrackingConsentType;\n private _logger: Logger;\n private _sessionData: SessionData;\n private _storage: StorageApi;\n private _storageKey: string;\n\n constructor(options: {\n storage: StorageApi;\n storageKey: string;\n logger: Logger;\n defaultTrackingConsent: TrackingConsentType;\n }) {\n this._storage = options.storage;\n this._storageKey = options.storageKey;\n this._logger = options.logger;\n this._defaultTrackingConsent =\n options.defaultTrackingConsent ?? TrackingConsent.PENDING;\n this._sessionData = this._createDefaultSessionData();\n }\n\n init(): void {\n const storedData = this._storage.getItem(this._storageKey);\n\n if (!storedData) {\n this._sessionData = this._createDefaultSessionData();\n this._persistToStorage();\n return;\n }\n\n try {\n const parsedData = JSON.parse(storedData) as Partial<SessionData>;\n\n this._sessionData = {\n visitorId: parsedData.visitorId || this._generateVisitorId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n userId: parsedData.userId || null,\n lastEventAt: parsedData.lastEventAt || null,\n trackingConsent: isValidTrackingConsent(parsedData.trackingConsent)\n ? parsedData.trackingConsent\n : this._defaultTrackingConsent,\n };\n } catch (error) {\n this._logger.warnDev(\n 'Failed to parse storage data. Resetting session data.'\n );\n this._sessionData = this._createDefaultSessionData();\n }\n\n this._persistToStorage();\n }\n\n getVisitorId(): VisitorId {\n return this._sessionData.visitorId;\n }\n\n getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getUserId(): UserId | null {\n return this._sessionData.userId;\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n setUserId(userId: UserId | null): void {\n this._sessionData.userId = userId;\n this._persistToStorage();\n }\n\n setTrackingConsent(consent: TrackingConsentType): void {\n this._sessionData.trackingConsent = consent;\n this._persistToStorage();\n }\n\n updateLastEventAt(timestamp: string): void {\n this._sessionData.lastEventAt = timestamp;\n this._persistToStorage();\n }\n\n renewSessionIfNeeded(): boolean {\n const shouldRenew = this._shouldRenewSession();\n\n if (shouldRenew) {\n this._renewSession();\n this._persistToStorage();\n return true;\n }\n\n return false;\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n resetTrackingConsent = false,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetVisitorId) {\n this._sessionData.visitorId = this._generateVisitorId();\n }\n\n if (resetSessionId) {\n this._sessionData.sessionId = this._generateSessionId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.userId = null;\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n visitorId: this._generateVisitorId(),\n sessionId: this._generateSessionId(),\n userId: null,\n lastEventAt: null,\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateVisitorId(): VisitorId {\n return generateId(PREFIX_VISITOR_ID);\n }\n\n private _shouldRenewSession(): boolean {\n const { lastEventAt } = this._sessionData;\n\n if (!lastEventAt) {\n return true;\n }\n\n const now = new Date().getTime();\n const lastEventTime = new Date(lastEventAt).getTime();\n const timeSinceLastEvent = now - lastEventTime;\n\n return timeSinceLastEvent > SESSION_EXPIRATION_TIME_MS;\n }\n\n private _renewSession(): void {\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.lastEventAt = null;\n }\n\n private _persistToStorage(): void {\n try {\n this._storage.setItem(\n this._storageKey,\n JSON.stringify(this._sessionData)\n );\n } catch (error) {\n this._logger.warnDev('Failed to persist session data to storage.');\n }\n }\n}\n\nfunction isValidTrackingConsent(value: unknown): value is TrackingConsentType {\n return (\n typeof value === 'string' &&\n Object.values(TrackingConsent).includes(value as TrackingConsentType)\n );\n}\n","import { STORAGE_KEY_TEST } from '../constants';\nimport { safelyRunOnBrowser } from './safelyRunOnBrowser';\n\nexport type StorageType =\n | 'localStorage'\n | 'sessionStorage'\n | 'cookie'\n | 'memory'\n | 'localStorage+cookie';\n\nexport interface StorageApi {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n migrate(fromStorage: StorageApi, keys: string[]): void;\n}\n\nfunction migrateKeys(\n toStorage: StorageApi,\n fromStorage: StorageApi,\n keys: string[]\n): void {\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n toStorage.setItem(key, value);\n fromStorage.removeItem(key);\n }\n }\n}\n\nclass MemoryStore implements StorageApi {\n private store: Record<string, string> = {};\n getItem(key: string): string | null {\n return this.store[key] ?? null;\n }\n setItem(key: string, value: string) {\n this.store[key] = value;\n }\n removeItem(key: string) {\n delete this.store[key];\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass CookieStore implements StorageApi {\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n const match = window.document.cookie.match(\n new RegExp('(^| )' + key + '=([^;]+)')\n );\n return match ? decodeURIComponent(match[2]) : null;\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=${encodeURIComponent(value)}; path=/;`;\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n window.document.cookie = `${key}=; Max-Age=0; path=/;`;\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass WebStorageStore implements StorageApi {\n constructor(private storage: 'localStorage' | 'sessionStorage') {}\n getItem(key: string): string | null {\n return safelyRunOnBrowser<string | null>(\n ({ window }) => {\n try {\n return window[this.storage].getItem(key);\n } catch {\n return null;\n }\n },\n () => null\n );\n }\n setItem(key: string, value: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].setItem(key, value);\n } catch {\n /* ignore */\n }\n });\n }\n removeItem(key: string) {\n safelyRunOnBrowser(({ window }) => {\n try {\n window[this.storage].removeItem(key);\n } catch {\n /* ignore */\n }\n });\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n migrateKeys(this, fromStorage, keys);\n }\n}\n\nclass LocalPlusCookieStore implements StorageApi {\n private localStore = new WebStorageStore('localStorage');\n private cookieStore = new CookieStore();\n getItem(key: string): string | null {\n return this.localStore.getItem(key) ?? this.cookieStore.getItem(key);\n }\n setItem(key: string, value: string) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n removeItem(key: string) {\n this.localStore.removeItem(key);\n this.cookieStore.removeItem(key);\n }\n migrate(fromStorage: StorageApi, keys: string[]) {\n // Migrate to both localStorage and cookie without removing from source yet\n for (const key of keys) {\n const value = fromStorage.getItem(key);\n if (value !== null) {\n this.localStore.setItem(key, value);\n this.cookieStore.setItem(key, value);\n }\n }\n\n for (const key of keys) {\n fromStorage.removeItem(key);\n }\n }\n}\n\nfunction testStorageSupport(\n storageType: 'localStorage' | 'sessionStorage' | 'cookie'\n) {\n return safelyRunOnBrowser(\n ({ window }) => {\n try {\n if (storageType === 'cookie') {\n window.document.cookie = `${STORAGE_KEY_TEST}=1`;\n const supported =\n window.document.cookie.indexOf(`${STORAGE_KEY_TEST}=`) !== -1;\n window.document.cookie = `${STORAGE_KEY_TEST}=; Max-Age=0`;\n return supported;\n } else {\n window[storageType].setItem(STORAGE_KEY_TEST, '1');\n window[storageType].removeItem(STORAGE_KEY_TEST);\n return true;\n }\n } catch {\n return false;\n }\n },\n () => false\n );\n}\n\nexport function selectStorage(\n type: StorageType | 'unknown',\n params: { onFallback: (message: string) => void }\n): StorageApi {\n const { onFallback } = params;\n\n switch (type) {\n case 'localStorage': {\n if (testStorageSupport('localStorage')) {\n return new WebStorageStore('localStorage');\n }\n onFallback(\n 'localStorage not supported, falling back to localStorage+cookie.'\n );\n return selectStorage('localStorage+cookie', params);\n }\n\n case 'localStorage+cookie': {\n const localStorageSupported = testStorageSupport('localStorage');\n const cookieSupported = testStorageSupport('cookie');\n\n if (localStorageSupported && cookieSupported) {\n return new LocalPlusCookieStore();\n } else if (cookieSupported) {\n onFallback(\n 'localStorage+cookie not fully supported, falling back to cookie.'\n );\n return new CookieStore();\n } else if (localStorageSupported) {\n onFallback('cookie not supported, falling back to localStorage.');\n return new WebStorageStore('localStorage');\n } else {\n onFallback(\n 'Neither localStorage nor cookie supported, falling back to memory.'\n );\n return new MemoryStore();\n }\n }\n\n case 'sessionStorage': {\n if (testStorageSupport('sessionStorage')) {\n return new WebStorageStore('sessionStorage');\n }\n onFallback('sessionStorage not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'cookie': {\n if (testStorageSupport('cookie')) {\n return new CookieStore();\n }\n onFallback('cookie not supported, falling back to memory.');\n return new MemoryStore();\n }\n\n case 'memory': {\n return new MemoryStore();\n }\n\n default: {\n throw new Error(\n `Unknown storage type: \"${type}\". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`\n );\n }\n }\n}\n","import {\n RESERVED_USER_IDS,\n RESERVED_USER_IDS_CASE_SENSITIVE,\n} from '../constants';\n\nconst reservedIdentifiersList = [\n ...RESERVED_USER_IDS,\n ...RESERVED_USER_IDS_CASE_SENSITIVE,\n]\n .map(id => `- \"${id}\"`)\n .join('\\n');\nconst reservedIdentifiersInfo = `List of reserved identifiers:\\n${reservedIdentifiersList}`;\n\nexport function validateUserId(userId: string): void {\n if (!userId || userId.trim() === '') {\n throw new Error('User ID cannot be empty or contain only whitespace.');\n }\n\n const isCaseInsensitiveBlocked = RESERVED_USER_IDS.some(\n blockedId => userId.toLowerCase() === blockedId.toLowerCase()\n );\n\n if (isCaseInsensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n\n const isCaseSensitiveBlocked = RESERVED_USER_IDS_CASE_SENSITIVE.has(userId);\n\n if (isCaseSensitiveBlocked) {\n throw new Error(\n `User ID \"${userId}\" is a reserved identifier and cannot be used.\\n\\n` +\n reservedIdentifiersInfo\n );\n }\n}\n","import {\n AUTO_CAPTURE_INTERVAL_MS,\n DEFAULT_BASE_URL,\n DEFAULT_ENVIRONMENT,\n DEFAULT_PERSISTENCE,\n EVENT_PAGEVIEW,\n keyBuilder,\n MAX_EVENT_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { EventQueue } from './lib/eventQueue';\nimport { getViewport } from './lib/getViewport';\nimport { invariant } from './lib/invariant';\nimport { createLogger } from './lib/logger';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\nimport { SessionManager } from './lib/sessionManager';\nimport {\n selectStorage,\n type StorageApi,\n type StorageType,\n} from './lib/storage';\nimport { validateUserId } from './lib/validateUserId';\nimport {\n EventContext,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n UserTraits,\n} from './types';\n\nexport interface AltertableConfig {\n /**\n * The base URL of the Altertable API.\n * @default https://api.altertable.ai\n */\n baseUrl?: string;\n /**\n * The environment of the application.\n * @default \"production\"\n */\n environment?: string;\n /**\n * Whether to automatically capture page views and events.\n * @default true\n */\n autoCapture?: boolean;\n /**\n * The release ID of the application.\n * This is helpful to identify the version of the application an event is coming from.\n */\n release?: string;\n /**\n * Whether to log events to the console.\n * @default false\n */\n debug?: boolean;\n /**\n * The persistence strategy for storing IDs.\n * @default \"localStorage+cookie\"\n */\n persistence?: StorageType;\n /**\n * The tracking consent state.\n * @default \"pending\"\n */\n trackingConsent?: TrackingConsentType;\n}\n\nexport class Altertable {\n private _apiKey: string;\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _eventQueue: EventQueue<EventPayload | IdentifyPayload>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _sessionManager: SessionManager | undefined;\n private _storage: StorageApi | undefined;\n private _storageKey: string | undefined;\n\n constructor() {\n this._lastUrl = null;\n this._referrer = null;\n this._eventQueue = new EventQueue(MAX_EVENT_QUEUE_SIZE);\n }\n\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._apiKey = apiKey;\n this._config = config;\n this._storageKey = keyBuilder(\n apiKey,\n this._config.environment || DEFAULT_ENVIRONMENT\n );\n this._referrer = safelyRunOnBrowser<string | null>(\n ({ window }) => window.document.referrer || null,\n () => null\n );\n this._lastUrl = safelyRunOnBrowser<string | null>(\n ({ window }) => window.location.href || null,\n () => null\n );\n const persistence: StorageType = config.persistence ?? DEFAULT_PERSISTENCE;\n this._storage = selectStorage(persistence, {\n onFallback: message => this._logger.warn(message),\n });\n\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: config.trackingConsent ?? TrackingConsent.PENDING,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n this._handleAutoCaptureChange(config.autoCapture ?? true);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n configure(updates: Partial<AltertableConfig>) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before configuring.'\n );\n\n if (\n updates.autoCapture !== undefined &&\n updates.autoCapture !== this._config.autoCapture\n ) {\n this._handleAutoCaptureChange(updates.autoCapture);\n }\n\n if (\n updates.persistence !== undefined &&\n updates.persistence !== this._config.persistence\n ) {\n const previousStorage = this._storage;\n this._storage = selectStorage(updates.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._storage.migrate(previousStorage, [this._storageKey]);\n }\n\n const currentTrackingConsent = this._sessionManager.getTrackingConsent();\n if (\n updates.trackingConsent !== undefined &&\n updates.trackingConsent !== currentTrackingConsent\n ) {\n this._sessionManager.setTrackingConsent(updates.trackingConsent);\n\n if (\n currentTrackingConsent !== TrackingConsent.GRANTED &&\n updates.trackingConsent === TrackingConsent.GRANTED\n ) {\n const queuedEvents = this._eventQueue.flush();\n if (queuedEvents.length > 0) {\n queuedEvents.forEach(event => {\n this._processEvent(event.eventType, event.payload, event.context);\n });\n }\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._eventQueue.clear();\n }\n }\n\n this._config = { ...this._config, ...updates };\n }\n\n private _handleAutoCaptureChange(enableAutoCapture: boolean) {\n this._cleanupAutoCapture?.();\n\n if (enableAutoCapture) {\n if (this._lastUrl) {\n this.page(this._lastUrl);\n }\n\n const checkForChanges = this._checkForChanges.bind(this);\n const intervalId = setInterval(checkForChanges, AUTO_CAPTURE_INTERVAL_MS);\n\n safelyRunOnBrowser(({ window }) => {\n window.addEventListener('popstate', checkForChanges);\n window.addEventListener('hashchange', checkForChanges);\n });\n\n this._cleanupAutoCapture = () => {\n clearInterval(intervalId);\n safelyRunOnBrowser(({ window }) => {\n window.removeEventListener('popstate', checkForChanges);\n window.removeEventListener('hashchange', checkForChanges);\n });\n };\n } else {\n this._cleanupAutoCapture = undefined;\n }\n }\n\n identify(userId: string, traits: UserTraits = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before identifying users.'\n );\n\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n this._sessionManager.setUserId(userId);\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n updateTraits(traits: UserTraits) {\n const userId = this._sessionManager.getUserId();\n invariant(\n userId,\n 'User must be identified with identify() before updating traits.'\n );\n\n const context = this._getEventContext();\n this._processEvent(\n 'identify',\n {\n environment: context.environment,\n traits,\n user_id: userId,\n visitor_id: context.visitor_id,\n },\n context\n );\n }\n\n reset({\n resetVisitorId = false,\n resetSessionId = true,\n }: {\n resetVisitorId?: boolean;\n resetSessionId?: boolean;\n } = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before resetting.'\n );\n\n this._sessionManager.reset({ resetVisitorId, resetSessionId });\n }\n\n page(url: string) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking page views.'\n );\n\n const parsedUrl = new URL(url);\n const urlWithoutSearch = `${parsedUrl.origin}${parsedUrl.pathname}`;\n this.track(EVENT_PAGEVIEW, {\n [PROPERTY_URL]: urlWithoutSearch,\n [PROPERTY_VIEWPORT]: getViewport(),\n [PROPERTY_REFERER]: this._referrer,\n ...Object.fromEntries(parsedUrl.searchParams),\n });\n }\n\n track(event: string, properties: EventProperties = {}) {\n invariant(\n this._isInitialized,\n 'The client must be initialized with init() before tracking events.'\n );\n\n this._sessionManager.renewSessionIfNeeded();\n const timestamp = new Date().toISOString();\n this._sessionManager.updateLastEventAt(timestamp);\n\n const context = this._getEventContext();\n const payload: EventPayload = {\n timestamp,\n event,\n environment: context.environment,\n user_id: context.user_id,\n session_id: context.session_id,\n visitor_id: context.visitor_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...properties,\n },\n };\n\n this._processEvent('track', payload, context);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionManager.getTrackingConsent();\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this.page(currentUrl);\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n }\n });\n }\n\n private _getEventContext(): EventContext {\n return {\n environment: this._config.environment || DEFAULT_ENVIRONMENT,\n user_id: this._sessionManager.getUserId(),\n visitor_id: this._sessionManager.getVisitorId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload | IdentifyPayload>(\n eventType: EventType,\n payload: TPayload,\n context: EventContext\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._request(`/${eventType}`, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._eventQueue.enqueue(eventType, payload, context);\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private _request(path: string, body: unknown): void {\n invariant(this._apiKey, 'Missing API key');\n invariant(this._config, 'Missing configuration');\n\n const url = `${this._config.baseUrl || DEFAULT_BASE_URL}${path}`;\n const payload = JSON.stringify(body);\n\n /* eslint-disable no-restricted-globals */\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n const beaconUrl = `${url}?apiKey=${encodeURIComponent(this._apiKey)}`;\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(beaconUrl, blob);\n } /* eslint-enable no-restricted-globals */ else {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._apiKey}`,\n },\n body: payload,\n });\n }\n }\n}\n","import { TrackingConsent } from './constants';\nimport { Altertable, type AltertableConfig } from './core';\nimport { safelyRunOnBrowser } from './lib/safelyRunOnBrowser';\n\nexport type { Altertable, AltertableConfig };\nexport { TrackingConsent };\n\ndeclare global {\n interface Window {\n Altertable: Altertable | Array<Array<unknown>> | undefined;\n }\n}\n\nexport const altertable = new Altertable();\n\nsafelyRunOnBrowser(({ window }) => {\n const stub = window.Altertable;\n if (stub && Array.isArray(stub)) {\n for (const item of stub) {\n const method = item[0];\n const args = item.slice(1);\n (altertable[method as keyof Altertable] as any)(...args);\n }\n }\n\n window.Altertable = altertable;\n});\n"],"mappings":"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","names":["createKeyBuilder","prefix","separator","parts","DEFAULT_BASE_URL","DEFAULT_ENVIRONMENT","DEFAULT_PERSISTENCE","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_EVENT_QUEUE_SIZE","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","EventQueue","queueMaxSize","eventType","payload","context","events","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","invariant","condition","message","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabelLabel","userLabelStyle","createLabelElement","userValueLabel","userValueStyle","createValueElement","visitorLabelLabel","visitorLabelStyle","visitorValueLabel","visitorValueStyle","sessionLabelLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","value","getEnvironmentColor","environment","TrackingConsent","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetVisitorId","resetSessionId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_VISITOR_ID","lastEventAt","now","lastEventTime","SESSION_EXPIRATION_TIME_MS","value","migrateKeys","toStorage","fromStorage","keys","key","value","MemoryStore","CookieStore","safelyRunOnBrowser","window","match","WebStorageStore","storage","LocalPlusCookieStore","testStorageSupport","storageType","STORAGE_KEY_TEST","supported","selectStorage","type","params","onFallback","localStorageSupported","cookieSupported","reservedIdentifiersList","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","id","reservedIdentifiersInfo","validateUserId","userId","blockedId","Altertable","createLogger","EventQueue","MAX_EVENT_QUEUE_SIZE","apiKey","config","invariant","keyBuilder","DEFAULT_ENVIRONMENT","safelyRunOnBrowser","window","persistence","DEFAULT_PERSISTENCE","selectStorage","message","SessionManager","TrackingConsent","updates","previousStorage","currentTrackingConsent","queuedEvents","event","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","resetVisitorId","resetSessionId","url","parsedUrl","urlWithoutSearch","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","getViewport","PROPERTY_REFERER","properties","timestamp","payload","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","trackingConsent","currentUrl","eventType","path","body","DEFAULT_BASE_URL","beaconUrl","blob","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@altertable/altertable-js",
3
3
  "description": "JavaScript SDK to capture and send events to Altertable.",
4
- "version": "0.5.2",
4
+ "version": "0.5.3",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/altertable-ai/altertable-js",
7
7
  "repository": "altertable-ai/altertable-js",