@altertable/altertable-js 1.0.6 → 1.0.7

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,10 +1,12 @@
1
- /*! @altertable/altertable-js 1.0.6 (UNRELEASED 8b22b09) | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
- var Altertable=(()=>{var V=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var Pe=(n,e)=>{for(var t in e)V(n,t,{get:e[t],enumerable:!0})},xe=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ae(e))!Re.call(n,s)&&s!==t&&V(n,s,{get:()=>e[s],enumerable:!(r=we(e,s))||r.enumerable});return n};var $e=n=>xe(V({},"__esModule",{value:!0}),n);var ze={};Pe(ze,{TrackingConsent:()=>o,altertable:()=>Z});function ee(n,e){return(...t)=>[n,...t].join(e)}var Ue="atbl",q=ee(Ue,"."),f=q("check"),te="session",ne="anonymous",re="device",Ne=1e3*60,se=100,ie=30*Ne,F=1e3,oe=5e3,ae="$pageview",ce="$lib",le="$lib_version",ge="$referer",ue="$release",y="$url",de="$viewport",o={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},Q=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],z=new Set(["[object Object]","0","NaN","none","None","null"]);var C=class extends Error{constructor(e){super(e),this.name="AltertableError"}},I=class extends C{constructor(t,r,s,c,i){super(`HTTP ${t}: ${r}${s?` (${s})`:""}`);this.status=t;this.statusText=r;this.errorCode=s;this.details=c;this.requestContext=i;this.name="ApiError"}},D=class extends C{constructor(t,r){super(t);this.cause=r;this.name="NetworkError"}};function pe(n){return n instanceof C}function me(n){return n instanceof I}function _e(n){return n instanceof D}function w(n,e){if(!n)throw new G(`[Altertable] ${typeof e=="function"?e():e}`)}var G=class n extends Error{constructor(e){super(e),Object.setPrototypeOf(this,n.prototype)}};function he(n=""){return`https://altertable.ai/dashboard${n}`}function fe(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v1.0.6 %c\u2022 Debug mode enabled";P.current[e]||(P.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[r,s]=K(e.event==="$pageview"?"Page":"Track"),[c,i]=Be(e.event==="$pageview"?String(e.properties[y]):e.event),[l,g]=Y(e.environment),[u,p]=Ve(e.timestamp),[d,m]=W(t);console.groupCollapsed(`[${n}] %c${r}%c ${c} %c[${l}] %c${u} %c${d}`,s,i,g,p,m);let[S,T]=_("User ID"),[k,b]=h(e.distinct_id??"Not set"),[ve,Ee]=_("Anonymous ID"),[Se,Te]=h(e.anonymous_id??"Not set"),[ke,be]=_("Session ID"),[Ce,De]=h(e.session_id??"Not set");console.log(`%c${S} %c${k}`,T,b),console.log(`%c${ve} %c${Se}`,Ee,Te),console.log(`%c${ke} %c${Ce}`,be,De),console.table(e.properties),console.groupEnd()},logIdentify:(e,{trackingConsent:t})=>{let[r,s]=K("Identify"),[c,i]=Y(e.environment),[l,g]=W(t);console.groupCollapsed(`[${n}] %c${r}%c ${e.distinct_id} %c[${c}] %c${l}`,s,"font-weight: 600;",i,g);let[u,p]=_("Distinct ID"),[d,m]=h(e.distinct_id??"Not set"),[S,T]=_("Anonymous ID"),[k,b]=h(e.anonymous_id??"Not set");console.log(`%c${u} %c${d}`,p,m),console.log(`%c${S} %c${k}`,T,b),console.table(e.traits),console.groupEnd()},logAlias:(e,{trackingConsent:t})=>{let[r,s]=K("Alias"),[c,i]=Y(e.environment),[l,g]=W(t);console.groupCollapsed(`[${n}] %c${r}%c ${e.distinct_id} %c[${c}] %c${l}`,s,"font-weight: 600;",i,g);let[u,p]=_("Distinct ID"),[d,m]=h(e.distinct_id??"Not set"),[S,T]=_("New User ID"),[k,b]=h(e.new_user_id??"Not set");console.log(`%c${u} %c${d}`,p,m),console.log(`%c${S} %c${k}`,T,b),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!s){P.current[r]=!0;let c=`[${n}] ${r}`;console.warn(c,...t);try{throw new Error(c)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var P={current:{}};function Le(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function Oe(n){switch(n){case"Page":return"#64748b";case"Identify":return"#a855f7";case"Track":return"#10b981";default:return"#1e293b"}}function K(n){return[n,`background: ${Oe(n)}; color: #ffffff; padding: 2px 8px; border-radius: 6px; font-weight: 400;`]}function Be(n){return[n==="$pageview"?"Page Viewed":n,"font-weight: 600;"]}function Y(n){return[n,`color: ${Me(n)}; font-weight: 400;`]}function Me(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function Ve(n){return[Le(n),"color: #64748b; font-weight: 400;"]}function _(n){return[n,"color: #64748b; font-size: 11px;"]}function h(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 W(n){switch(n){case o.GRANTED:return["",""];case o.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case o.PENDING:case o.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 X(n){try{let e=new URL(n);return{baseUrl:`${e.origin}${e.pathname}`,searchParams:Object.fromEntries(e.searchParams)}}catch{return null}}var x=class{_items=[];_maxSize;_onDropOldest;constructor(e){this._maxSize=e.capacity,this._onDropOldest=e.onDropOldest}enqueue(e){if(this._items.length>=this._maxSize){let t=this._items.shift();t&&this._onDropOldest?.(t)}this._items.push(e)}flush(){let e=[...this._items];return this._items=[],e}clear(){this._items=[]}getSize(){return this._items.length}getAll(){return this._items}};function ye(){return typeof window<"u"&&typeof navigator<"u"&&typeof navigator.sendBeacon=="function"}var $=class{_config;constructor(e){this._config=e}_constructUrl(e){return`${this._config.baseUrl}${e}?apiKey=${encodeURIComponent(this._config.apiKey)}`}async send(e,t){return ye()?this._sendWithBeacon(e,t):this._sendWithFetch(e,t)}async _sendWithBeacon(e,t){let r=this._constructUrl(e),s=new Blob([JSON.stringify(t)],{type:"application/json"});try{if(!navigator.sendBeacon(r,s))return this._sendWithFetch(e,t)}catch{return this._sendWithFetch(e,t)}}async _sendWithFetch(e,t){let r=this._constructUrl(e),s=new AbortController,c=setTimeout(()=>s.abort(),this._config.requestTimeout);try{let i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0,signal:s.signal});if(!i.ok){let l;try{l=await i.json()}catch{}throw new I(i.status,i.statusText,l?.error_code,l,{url:r,method:"POST",payload:t})}}catch(i){throw i instanceof I?i:new D(i instanceof Error?i.message:"Network request failed",i)}finally{clearTimeout(c)}}};function a(n,e=()=>{}){return typeof window>"u"?e():n({window})}function U(){return a(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function N(){return{timestamp:new Date().toISOString(),url:a(({window:n})=>n.location.href||null,()=>null),referrer:a(({window:n})=>n.document.referrer||null,()=>null),viewport:U()}}function L(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 O=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??o.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={deviceId:t.deviceId||this._generateDeviceId(),distinctId:t.distinctId||this._generateAnonymousId(),sessionId:t.sessionId||this._generateSessionId(),anonymousId:t.anonymousId||null,lastEventAt:t.lastEventAt||null,trackingConsent:qe(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getSessionId(){return this._sessionData.sessionId}getDeviceId(){return this._sessionData.deviceId}getDistinctId(){return this._sessionData.distinctId}getAnonymousId(){return this._sessionData.anonymousId}isIdentified(){return!!this._sessionData.anonymousId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}identify(e){this._sessionData.anonymousId=this._sessionData.distinctId,this._sessionData.distinctId=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({resetDeviceId:e=!1,resetTrackingConsent:t=!1}={}){e&&(this._sessionData.deviceId=this._generateDeviceId()),t&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.sessionId=this._generateSessionId(),this._sessionData.anonymousId=null,this._sessionData.distinctId=this._generateAnonymousId(),this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{anonymousId:null,deviceId:this._generateDeviceId(),distinctId:this._generateAnonymousId(),lastEventAt:null,sessionId:this._generateSessionId(),trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return L(te)}_generateDeviceId(){return L(re)}_generateAnonymousId(){return L(ne)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),r=new Date(e).getTime();return t-r>ie}_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 qe(n){return typeof n=="string"&&Object.values(o).includes(n)}function H(n,e,t){for(let r of t){let s=e.getItem(r);s!==null&&(n.setItem(r,s),e.removeItem(r))}}var v=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){H(this,e,t)}},R=class{getItem(e){return a(({window:t})=>{let r=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return r?decodeURIComponent(r[2]):null},()=>null)}setItem(e,t){a(({window:r})=>{r.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){a(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){H(this,e,t)}},E=class{constructor(e){this.storage=e}getItem(e){return a(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){a(({window:r})=>{try{r[this.storage].setItem(e,t)}catch{}})}removeItem(e){a(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){H(this,e,t)}},j=class{localStore=new E("localStorage");cookieStore=new R;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 r of t){let s=e.getItem(r);s!==null&&(this.localStore.setItem(r,s),this.cookieStore.setItem(r,s))}for(let r of t)e.removeItem(r)}};function A(n){return a(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${f}=1`;let t=e.document.cookie.indexOf(`${f}=`)!==-1;return e.document.cookie=`${f}=; Max-Age=0`,t}else return e[n].setItem(f,"1"),e[n].removeItem(f),!0}catch{return!1}},()=>!1)}function B(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return A("localStorage")?new E("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),B("localStorage+cookie",e));case"localStorage+cookie":{let r=A("localStorage"),s=A("cookie");return r&&s?new j:s?(t("localStorage+cookie not fully supported, falling back to cookie."),new R):r?(t("cookie not supported, falling back to localStorage."),new E("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new v)}case"sessionStorage":return A("sessionStorage")?new E("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new v);case"cookie":return A("cookie")?new R:(t("cookie not supported, falling back to memory."),new v);case"memory":return new v;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Fe=[...Q,...z].map(n=>`- "${n}"`).join(`
1
+ /*! @altertable/altertable-js 1.0.7 | MIT License | Altertable | https://github.com/altertable-ai/altertable-js */
2
+ var Altertable=(()=>{var M=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var Pe=(n,e)=>{for(var t in e)M(n,t,{get:e[t],enumerable:!0})},xe=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ae(e))!Re.call(n,s)&&s!==t&&M(n,s,{get:()=>e[s],enumerable:!(r=we(e,s))||r.enumerable});return n};var $e=n=>xe(M({},"__esModule",{value:!0}),n);var ze={};Pe(ze,{TrackingConsent:()=>o,altertable:()=>Z});function ee(n,e){return(...t)=>[n,...t].join(e)}var Ue="atbl",V=ee(Ue,"."),f=V("check"),te="session",ne="anonymous",re="device",Ne=1e3*60,se=100,ie=30*Ne,q=1e3,oe=5e3,ae="$pageview",ce="$lib",le="$lib_version",ge="$referer",ue="$release",y="$url",de="$viewport",o={DENIED:"denied",DISMISSED:"dismissed",GRANTED:"granted",PENDING:"pending"},F=["anonymous_id","anonymous","distinct_id","distinctid","false","guest","id","not_authenticated","true","undefined","user_id","user","visitor_id","visitor"],Q=new Set(["[object Object]","0","NaN","none","None","null"]);var C=class extends Error{constructor(e){super(e),this.name="AltertableError"}},I=class extends C{constructor(t,r,s,c,i){super(`HTTP ${t}: ${r}${s?` (${s})`:""}`);this.status=t;this.statusText=r;this.errorCode=s;this.details=c;this.requestContext=i;this.name="ApiError"}},D=class extends C{constructor(t,r){super(t);this.cause=r;this.name="NetworkError"}};function pe(n){return n instanceof C}function me(n){return n instanceof I}function _e(n){return n instanceof D}function G(n,e){if(!n)throw new z(`[Altertable] ${typeof e=="function"?e():e}`)}var z=class n extends Error{constructor(e){super(e),Object.setPrototypeOf(this,n.prototype)}};function he(n=""){return`https://altertable.ai/dashboard${n}`}function fe(n){return{log:(...e)=>{console.log(`[${n}]`,...e)},logHeader:()=>{let e="Altertable v1.0.7 %c\u2022 Debug mode enabled";R.current[e]||(R.current[e]=!0,console.log(e,"color: #64748b;"))},logEvent:(e,{trackingConsent:t})=>{let[r,s]=K(e.event==="$pageview"?"Page":"Track"),[c,i]=Be(e.event==="$pageview"?String(e.properties[y]):e.event),[l,g]=Y(e.environment),[u,p]=Ve(e.timestamp),[d,m]=W(t);console.groupCollapsed(`[${n}] %c${r}%c ${c} %c[${l}] %c${u} %c${d}`,s,i,g,p,m);let[S,T]=_("User ID"),[k,b]=h(e.distinct_id??"Not set"),[ve,Ee]=_("Anonymous ID"),[Se,Te]=h(e.anonymous_id??"Not set"),[ke,be]=_("Session ID"),[Ce,De]=h(e.session_id??"Not set");console.log(`%c${S} %c${k}`,T,b),console.log(`%c${ve} %c${Se}`,Ee,Te),console.log(`%c${ke} %c${Ce}`,be,De),console.table(e.properties),console.groupEnd()},logIdentify:(e,{trackingConsent:t})=>{let[r,s]=K("Identify"),[c,i]=Y(e.environment),[l,g]=W(t);console.groupCollapsed(`[${n}] %c${r}%c ${e.distinct_id} %c[${c}] %c${l}`,s,"font-weight: 600;",i,g);let[u,p]=_("Distinct ID"),[d,m]=h(e.distinct_id??"Not set"),[S,T]=_("Anonymous ID"),[k,b]=h(e.anonymous_id??"Not set");console.log(`%c${u} %c${d}`,p,m),console.log(`%c${S} %c${k}`,T,b),console.table(e.traits),console.groupEnd()},logAlias:(e,{trackingConsent:t})=>{let[r,s]=K("Alias"),[c,i]=Y(e.environment),[l,g]=W(t);console.groupCollapsed(`[${n}] %c${r}%c ${e.distinct_id} %c[${c}] %c${l}`,s,"font-weight: 600;",i,g);let[u,p]=_("Distinct ID"),[d,m]=h(e.distinct_id??"Not set"),[S,T]=_("New User ID"),[k,b]=h(e.new_user_id??"Not set");console.log(`%c${u} %c${d}`,p,m),console.log(`%c${S} %c${k}`,T,b),console.groupEnd()},warn:(...e)=>{console.warn(`[${n}]`,...e)},warnDev:(e,...t)=>{return;if(!s){R.current[r]=!0;let c=`[${n}] ${r}`;console.warn(c,...t);try{throw new Error(c)}catch{}}},error:(...e)=>{console.error(`[${n}]`,...e)}}}var R={current:{}};function Le(n){return new Date(n).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function Oe(n){switch(n){case"Page":return"#64748b";case"Identify":return"#a855f7";case"Track":return"#10b981";default:return"#1e293b"}}function K(n){return[n,`background: ${Oe(n)}; color: #ffffff; padding: 2px 8px; border-radius: 6px; font-weight: 400;`]}function Be(n){return[n==="$pageview"?"Page Viewed":n,"font-weight: 600;"]}function Y(n){return[n,`color: ${Me(n)}; font-weight: 400;`]}function Me(n){switch(n.toLocaleLowerCase().startsWith("prod")?"production":n){case"production":return"#ef4444";default:return"#3b82f6"}}function Ve(n){return[Le(n),"color: #64748b; font-weight: 400;"]}function _(n){return[n,"color: #64748b; font-size: 11px;"]}function h(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 W(n){switch(n){case o.GRANTED:return["",""];case o.DENIED:return["DENIED","background: #ef4444; color: #ffffff; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600;"];case o.PENDING:case o.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 X(n){try{let e=new URL(n);return{baseUrl:`${e.origin}${e.pathname}`,searchParams:Object.fromEntries(e.searchParams)}}catch{return null}}var P=class{_items=[];_maxSize;_onDropOldest;constructor(e){this._maxSize=e.capacity,this._onDropOldest=e.onDropOldest}enqueue(e){if(this._items.length>=this._maxSize){let t=this._items.shift();t&&this._onDropOldest?.(t)}this._items.push(e)}flush(){let e=[...this._items];return this._items=[],e}clear(){this._items=[]}getSize(){return this._items.length}getAll(){return this._items}};function ye(){return typeof window<"u"&&typeof navigator<"u"&&typeof navigator.sendBeacon=="function"}var x=class{_config;constructor(e){this._config=e}_constructUrl(e){return`${this._config.baseUrl}${e}?apiKey=${encodeURIComponent(this._config.apiKey)}`}async send(e,t){return ye()?this._sendWithBeacon(e,t):this._sendWithFetch(e,t)}async _sendWithBeacon(e,t){let r=this._constructUrl(e),s=new Blob([JSON.stringify(t)],{type:"application/json"});try{if(!navigator.sendBeacon(r,s))return this._sendWithFetch(e,t)}catch{return this._sendWithFetch(e,t)}}async _sendWithFetch(e,t){let r=this._constructUrl(e),s=new AbortController,c=setTimeout(()=>s.abort(),this._config.requestTimeout);try{let i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0,signal:s.signal});if(!i.ok){let l;try{l=await i.json()}catch{}throw new I(i.status,i.statusText,l?.error_code,l,{url:r,method:"POST",payload:t})}}catch(i){throw i instanceof I?i:new D(i instanceof Error?i.message:"Network request failed",i)}finally{clearTimeout(c)}}};function a(n,e=()=>{}){return typeof window>"u"?e():n({window})}function $(){return a(({window:n})=>`${n.innerWidth}x${n.innerHeight}`,()=>null)}function U(){return{timestamp:new Date().toISOString(),url:a(({window:n})=>n.location.href||null,()=>null),referrer:a(({window:n})=>n.document.referrer||null,()=>null),viewport:$()}}function N(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 L=class{_defaultTrackingConsent;_logger;_sessionData;_storage;_storageKey;constructor(e){this._storage=e.storage,this._storageKey=e.storageKey,this._logger=e.logger,this._defaultTrackingConsent=e.defaultTrackingConsent??o.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={deviceId:t.deviceId||this._generateDeviceId(),distinctId:t.distinctId||this._generateAnonymousId(),sessionId:t.sessionId||this._generateSessionId(),anonymousId:t.anonymousId||null,lastEventAt:t.lastEventAt||null,trackingConsent:qe(t.trackingConsent)?t.trackingConsent:this._defaultTrackingConsent}}catch{this._logger.warnDev("Failed to parse storage data. Resetting session data."),this._sessionData=this._createDefaultSessionData()}this._persistToStorage()}getSessionId(){return this._sessionData.sessionId}getDeviceId(){return this._sessionData.deviceId}getDistinctId(){return this._sessionData.distinctId}getAnonymousId(){return this._sessionData.anonymousId}isIdentified(){return!!this._sessionData.anonymousId}getLastEventAt(){return this._sessionData.lastEventAt}getTrackingConsent(){return this._sessionData.trackingConsent}identify(e){this._sessionData.anonymousId=this._sessionData.distinctId,this._sessionData.distinctId=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({resetDeviceId:e=!1,resetTrackingConsent:t=!1}={}){e&&(this._sessionData.deviceId=this._generateDeviceId()),t&&(this._sessionData.trackingConsent=this._defaultTrackingConsent),this._sessionData.sessionId=this._generateSessionId(),this._sessionData.anonymousId=null,this._sessionData.distinctId=this._generateAnonymousId(),this._sessionData.lastEventAt=null,this._persistToStorage()}_createDefaultSessionData(){return{anonymousId:null,deviceId:this._generateDeviceId(),distinctId:this._generateAnonymousId(),lastEventAt:null,sessionId:this._generateSessionId(),trackingConsent:this._defaultTrackingConsent}}_generateSessionId(){return N(te)}_generateDeviceId(){return N(re)}_generateAnonymousId(){return N(ne)}_shouldRenewSession(){let{lastEventAt:e}=this._sessionData;if(!e)return!0;let t=new Date().getTime(),r=new Date(e).getTime();return t-r>ie}_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 qe(n){return typeof n=="string"&&Object.values(o).includes(n)}function H(n,e,t){for(let r of t){let s=e.getItem(r);s!==null&&(n.setItem(r,s),e.removeItem(r))}}var v=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){H(this,e,t)}},A=class{getItem(e){return a(({window:t})=>{let r=t.document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return r?decodeURIComponent(r[2]):null},()=>null)}setItem(e,t){a(({window:r})=>{r.document.cookie=`${e}=${encodeURIComponent(t)}; path=/;`})}removeItem(e){a(({window:t})=>{t.document.cookie=`${e}=; Max-Age=0; path=/;`})}migrate(e,t){H(this,e,t)}},E=class{constructor(e){this.storage=e}getItem(e){return a(({window:t})=>{try{return t[this.storage].getItem(e)}catch{return null}},()=>null)}setItem(e,t){a(({window:r})=>{try{r[this.storage].setItem(e,t)}catch{}})}removeItem(e){a(({window:t})=>{try{t[this.storage].removeItem(e)}catch{}})}migrate(e,t){H(this,e,t)}},j=class{localStore=new E("localStorage");cookieStore=new A;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 r of t){let s=e.getItem(r);s!==null&&(this.localStore.setItem(r,s),this.cookieStore.setItem(r,s))}for(let r of t)e.removeItem(r)}};function w(n){return a(({window:e})=>{try{if(n==="cookie"){e.document.cookie=`${f}=1`;let t=e.document.cookie.indexOf(`${f}=`)!==-1;return e.document.cookie=`${f}=; Max-Age=0`,t}else return e[n].setItem(f,"1"),e[n].removeItem(f),!0}catch{return!1}},()=>!1)}function O(n,e){let{onFallback:t}=e;switch(n){case"localStorage":return w("localStorage")?new E("localStorage"):(t("localStorage not supported, falling back to localStorage+cookie."),O("localStorage+cookie",e));case"localStorage+cookie":{let r=w("localStorage"),s=w("cookie");return r&&s?new j:s?(t("localStorage+cookie not fully supported, falling back to cookie."),new A):r?(t("cookie not supported, falling back to localStorage."),new E("localStorage")):(t("Neither localStorage nor cookie supported, falling back to memory."),new v)}case"sessionStorage":return w("sessionStorage")?new E("sessionStorage"):(t("sessionStorage not supported, falling back to memory."),new v);case"cookie":return w("cookie")?new A:(t("cookie not supported, falling back to memory."),new v);case"memory":return new v;default:throw new Error(`Unknown storage type: "${n}". Valid types are: localStorage, sessionStorage, cookie, memory, localStorage+cookie.`)}}var Fe=[...F,...Q].map(n=>`- "${n}"`).join(`
3
3
  `),Ie=`List of reserved identifiers:
4
- ${Fe}`;function J(n){if(!n||n.trim()==="")throw new Error("User ID cannot be empty or contain only whitespace.");if(Q.some(r=>n.toLowerCase()===r.toLowerCase()))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
4
+ ${Fe}`;function J(n){if(!n||n.trim()==="")throw new Error("User ID cannot be empty or contain only whitespace.");if(F.some(r=>n.toLowerCase()===r.toLowerCase()))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
5
5
 
6
- `+Ie);if(z.has(n))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
6
+ `+Ie);if(Q.has(n))throw new Error(`User ID "${n}" is a reserved identifier and cannot be used.
7
7
 
8
- `+Ie)}var Qe={autoCapture:!0,baseUrl:"https://api.altertable.ai",debug:!1,environment:"production",persistence:"localStorage+cookie",release:void 0,trackingConsent:o.GRANTED},M=class{_cleanupAutoCapture;_config;_queue;_isInitialized=!1;_lastUrl;_logger=fe("Altertable");_referrer;_requester;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._queue=new x({capacity:F,onDropOldest:e=>{let t=e.type==="command"?e.method:e.eventType;this._logger.warnDev(`Queue is full (${F} items). Dropping ${t} call.`)}})}init(e,t={}){w(e,"Missing API key"),this._config={...Qe,...t},this._storageKey=q(e,this._config.environment),this._referrer=a(({window:s})=>s.document.referrer||null,()=>null),this._lastUrl=a(({window:s})=>s.location.href||null,()=>null),this._storage=B(this._config.persistence,{onFallback:s=>this._logger.warn(s)}),this._requester=new $({baseUrl:this._config.baseUrl,apiKey:e,requestTimeout:oe}),this._sessionManager=new O({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:this._config.trackingConsent}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader();let r=this._sessionManager.getTrackingConsent();return r===o.GRANTED?this._flushQueue():r===o.DENIED&&this._queue.clear(),this._handleAutoCaptureChange(this._config.autoCapture),()=>{this._cleanupAutoCapture?.()}}configure(e){if(w(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 r=this._storage;this._storage=B(e.persistence,{onFallback:s=>this._logger.warn(s)}),this._storage.migrate(r,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();e.trackingConsent!==void 0&&e.trackingConsent!==t&&(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==o.GRANTED&&e.trackingConsent===o.GRANTED?this._flushQueue():e.trackingConsent===o.DENIED&&this._queue.clear()),this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),r=setInterval(t,se);a(({window:s})=>{s.addEventListener("popstate",t),s.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(r),a(({window:s})=>{s.removeEventListener("popstate",t),s.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){try{J(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}if(!this._isInitialized){this._queue.enqueue({type:"command",method:"identify",args:[e,{...t}]});return}this._identify(e,{...t})}_identify(e,t={}){w(!this._sessionManager.isIdentified()||e===this._sessionManager.getDistinctId(),`User (${e}) is already identified as a different user (${this._sessionManager.getDistinctId()}). This usually indicates a development issue, as it would merge two separate identities. Call reset() before identifying a new user, or use alias() to link the new ID to the existing one.`),e!==this._sessionManager.getDistinctId()&&this._sessionManager.identify(e);let r=this._getContext(),s={environment:r.environment,device_id:r.device_id,distinct_id:r.distinct_id,traits:t,anonymous_id:r.anonymous_id};if(this._processEvent("identify",s),this._config.debug){let c=this._sessionManager.getTrackingConsent();this._logger.logIdentify(s,{trackingConsent:c})}}alias(e){try{J(e)}catch(t){throw new Error(`[Altertable] ${t.message}`)}if(!this._isInitialized){this._queue.enqueue({type:"command",method:"alias",args:[e]});return}this._alias(e)}_alias(e){let t=this._getContext(),r={environment:t.environment,device_id:t.device_id,anonymous_id:t.anonymous_id,distinct_id:t.distinct_id,new_user_id:e};if(this._processEvent("alias",r),this._config.debug){let s=this._sessionManager.getTrackingConsent();this._logger.logAlias(r,{trackingConsent:s})}}updateTraits(e){if(!this._isInitialized){this._queue.enqueue({type:"command",method:"updateTraits",args:[{...e}]});return}this._updateTraits({...e})}_updateTraits(e){let t=this._getContext();w(t.anonymous_id!==null,"User must be identified with identify() before updating traits.");let r={environment:t.environment,device_id:t.device_id,distinct_id:t.distinct_id,traits:e,anonymous_id:t.anonymous_id,session_id:t.session_id};if(this._processEvent("identify",r),this._config.debug){let s=this._sessionManager.getTrackingConsent();this._logger.logIdentify(r,{trackingConsent:s})}}reset({resetDeviceId:e=!1}={}){this._queue.clear(),this._isInitialized&&this._sessionManager.reset({resetDeviceId:e})}page(e){if(!this._isInitialized){this._queue.enqueue({type:"command",method:"page",runtimeContext:N(),args:[e]});return}this._page(e)}_page(e,t){let r=X(e),s=r?r.baseUrl:e,c=t?.viewport??U(),i=t?.referrer??this._referrer;this._track(ae,{[y]:s,[de]:c,[ge]:i,...r?.searchParams},t)}track(e,t={}){if(!this._isInitialized){this._queue.enqueue({type:"command",method:"track",runtimeContext:N(),args:[e,{...t}]});return}this._track(e,{...t})}_track(e,t,r=N()){this._sessionManager.renewSessionIfNeeded(),this._sessionManager.updateLastEventAt(r.timestamp);let s=this._getContext(),{[y]:c,...i}=t,l=c!==void 0,g=l?null:r.url,u=g?X(g):null,p=u?u.baseUrl:g,d={timestamp:r.timestamp,event:e,environment:s.environment,device_id:s.device_id,distinct_id:s.distinct_id,anonymous_id:s.anonymous_id,session_id:s.session_id,properties:{[ce]:"@altertable/altertable-js",[le]:"1.0.6",[ue]:this._config.release,[y]:l?c:p,...i}};if(this._processEvent("track",d),this._config.debug){let m=this._sessionManager.getTrackingConsent();this._logger.logEvent(d,{trackingConsent:m})}}getTrackingConsent(){return this._isInitialized?this._sessionManager.getTrackingConsent():o.PENDING}_flushQueue(){let e=this._queue.flush();if(e.length!==0){this._config.debug&&this._logger.log(`Processing ${e.length} queued ${e.length===1?"item":"items"}.`);for(let t of e)this._executeQueueItem(t)}}_executeQueueItem(e){if(e.type==="event"){this._sendEvent(e.eventType,e.payload);return}this._executeCommand(e)}_executeCommand(e){try{switch(e.method){case"identify":this._identify(...e.args);break;case"track":this._track(...e.args,e.runtimeContext);break;case"page":this._page(...e.args,e.runtimeContext);break;case"alias":this._alias(...e.args);break;case"updateTraits":this._updateTraits(...e.args);break}}catch(t){let r=t instanceof Error?t.message:String(t);this._logger.warnDev(`Failed to process queued ${e.method}() command:
9
- ${r}`)}}_checkForChanges(){a(({window:e})=>{let t=e.location.href;t!==this._lastUrl&&(this._referrer=this._lastUrl,this._lastUrl=t,this.page(t))})}_getContext(){return{environment:this._config.environment,device_id:this._sessionManager.getDeviceId(),distinct_id:this._sessionManager.getDistinctId(),anonymous_id:this._sessionManager.getAnonymousId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t){switch(this._sessionManager.getTrackingConsent()){case o.GRANTED:this._sendEvent(e,t);break;case o.PENDING:case o.DISMISSED:this._queue.enqueue({type:"event",eventType:e,payload:t});break;case o.DENIED:break}}async _sendEvent(e,t){try{await this._requester.send(`/${e}`,t)}catch(r){pe(r)&&this._config.onError?.(r),me(r)&&r.errorCode==="environment-not-found"?this._logger.warnDev(`Environment "${this._config.environment}" not found. Please create this environment in your Altertable dashboard at ${he(`/environments/new?name=${this._config.environment}`)} before tracking events.`):_e(r)?this._logger.error("Network error while sending event",{error:r.message,cause:r.cause,eventType:e}):this._logger.error("Failed to send event",{error:r,eventType:e,payload:t})}}};var Z=new M;a(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let r=t[0],s=t.slice(1);Z[r](...s)}n.Altertable=Z});return $e(ze);})();
8
+ `+Ie)}var Qe={autoCapture:!0,baseUrl:"https://api.altertable.ai",debug:!1,environment:"production",persistence:"localStorage+cookie",release:void 0,trackingConsent:o.GRANTED},B=class{_cleanupAutoCapture;_config;_queue;_isInitialized=!1;_lastUrl;_logger=fe("Altertable");_referrer;_requester;_sessionManager;_storage;_storageKey;constructor(){this._lastUrl=null,this._referrer=null,this._queue=new P({capacity:q,onDropOldest:e=>{let t=e.type==="command"?e.method:e.eventType;this._logger.warnDev(`Queue is full (${q} items). Dropping ${t} call.`)}})}init(e,t={}){G(e,"Missing API key"),this._config={...Qe,...t},this._storageKey=V(e,this._config.environment),this._referrer=a(({window:s})=>s.document.referrer||null,()=>null),this._lastUrl=a(({window:s})=>s.location.href||null,()=>null),this._storage=O(this._config.persistence,{onFallback:s=>this._logger.warn(s)}),this._requester=new x({baseUrl:this._config.baseUrl,apiKey:e,requestTimeout:oe}),this._sessionManager=new L({storage:this._storage,storageKey:this._storageKey,logger:this._logger,defaultTrackingConsent:this._config.trackingConsent}),this._sessionManager.init(),this._isInitialized=!0,this._config.debug&&this._logger.logHeader();let r=this._sessionManager.getTrackingConsent();return r===o.GRANTED?this._flushQueue():r===o.DENIED&&this._queue.clear(),this._handleAutoCaptureChange(this._config.autoCapture),()=>{this._cleanupAutoCapture?.()}}configure(e){if(G(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 r=this._storage;this._storage=O(e.persistence,{onFallback:s=>this._logger.warn(s)}),this._storage.migrate(r,[this._storageKey])}let t=this._sessionManager.getTrackingConsent();e.trackingConsent!==void 0&&e.trackingConsent!==t&&(this._sessionManager.setTrackingConsent(e.trackingConsent),t!==o.GRANTED&&e.trackingConsent===o.GRANTED?this._flushQueue():e.trackingConsent===o.DENIED&&this._queue.clear()),this._config={...this._config,...e}}_handleAutoCaptureChange(e){if(this._cleanupAutoCapture?.(),e){this._lastUrl&&this.page(this._lastUrl);let t=this._checkForChanges.bind(this),r=setInterval(t,se);a(({window:s})=>{s.addEventListener("popstate",t),s.addEventListener("hashchange",t)}),this._cleanupAutoCapture=()=>{clearInterval(r),a(({window:s})=>{s.removeEventListener("popstate",t),s.removeEventListener("hashchange",t)})}}else this._cleanupAutoCapture=void 0}identify(e,t={}){try{J(e)}catch(r){throw new Error(`[Altertable] ${r.message}`)}if(!this._isInitialized){this._queue.enqueue({type:"command",method:"identify",args:[e,{...t}]});return}this._identify(e,{...t})}_identify(e,t={}){this._sessionManager.isIdentified()&&e!==this._sessionManager.getDistinctId()&&(this._logger.warnDev(`User "${e}" is already identified as "${this._sessionManager.getDistinctId()}".
9
+
10
+ The session has been automatically reset. Use alias() to link the new ID to the existing one if intentional.`),this.reset()),e!==this._sessionManager.getDistinctId()&&this._sessionManager.identify(e);let r=this._getContext(),s={environment:r.environment,device_id:r.device_id,distinct_id:r.distinct_id,traits:t,anonymous_id:r.anonymous_id};if(this._processEvent("identify",s),this._config.debug){let c=this._sessionManager.getTrackingConsent();this._logger.logIdentify(s,{trackingConsent:c})}}alias(e){try{J(e)}catch(t){throw new Error(`[Altertable] ${t.message}`)}if(!this._isInitialized){this._queue.enqueue({type:"command",method:"alias",args:[e]});return}this._alias(e)}_alias(e){let t=this._getContext(),r={environment:t.environment,device_id:t.device_id,anonymous_id:t.anonymous_id,distinct_id:t.distinct_id,new_user_id:e};if(this._processEvent("alias",r),this._config.debug){let s=this._sessionManager.getTrackingConsent();this._logger.logAlias(r,{trackingConsent:s})}}updateTraits(e){if(!this._isInitialized){this._queue.enqueue({type:"command",method:"updateTraits",args:[{...e}]});return}this._updateTraits({...e})}_updateTraits(e){let t=this._getContext();if(t.anonymous_id===null){this._logger.warnDev("User must be identified with identify() before updating traits.");return}let r={environment:t.environment,device_id:t.device_id,distinct_id:t.distinct_id,traits:e,anonymous_id:t.anonymous_id,session_id:t.session_id};if(this._processEvent("identify",r),this._config.debug){let s=this._sessionManager.getTrackingConsent();this._logger.logIdentify(r,{trackingConsent:s})}}reset({resetDeviceId:e=!1}={}){this._queue.clear(),this._isInitialized&&this._sessionManager.reset({resetDeviceId:e})}page(e){if(!this._isInitialized){this._queue.enqueue({type:"command",method:"page",runtimeContext:U(),args:[e]});return}this._page(e)}_page(e,t){let r=X(e),s=r?r.baseUrl:e,c=t?.viewport??$(),i=t?.referrer??this._referrer;this._track(ae,{[y]:s,[de]:c,[ge]:i,...r?.searchParams},t)}track(e,t={}){if(!this._isInitialized){this._queue.enqueue({type:"command",method:"track",runtimeContext:U(),args:[e,{...t}]});return}this._track(e,{...t})}_track(e,t,r=U()){this._sessionManager.renewSessionIfNeeded(),this._sessionManager.updateLastEventAt(r.timestamp);let s=this._getContext(),{[y]:c,...i}=t,l=c!==void 0,g=l?null:r.url,u=g?X(g):null,p=u?u.baseUrl:g,d={timestamp:r.timestamp,event:e,environment:s.environment,device_id:s.device_id,distinct_id:s.distinct_id,anonymous_id:s.anonymous_id,session_id:s.session_id,properties:{[ce]:"@altertable/altertable-js",[le]:"1.0.7",[ue]:this._config.release,[y]:l?c:p,...i}};if(this._processEvent("track",d),this._config.debug){let m=this._sessionManager.getTrackingConsent();this._logger.logEvent(d,{trackingConsent:m})}}getTrackingConsent(){return this._isInitialized?this._sessionManager.getTrackingConsent():o.PENDING}_flushQueue(){let e=this._queue.flush();if(e.length!==0){this._config.debug&&this._logger.log(`Processing ${e.length} queued ${e.length===1?"item":"items"}.`);for(let t of e)this._executeQueueItem(t)}}_executeQueueItem(e){if(e.type==="event"){this._sendEvent(e.eventType,e.payload);return}this._executeCommand(e)}_executeCommand(e){try{switch(e.method){case"identify":this._identify(...e.args);break;case"track":this._track(...e.args,e.runtimeContext);break;case"page":this._page(...e.args,e.runtimeContext);break;case"alias":this._alias(...e.args);break;case"updateTraits":this._updateTraits(...e.args);break}}catch(t){let r=t instanceof Error?t.message:String(t);this._logger.warnDev(`Failed to process queued ${e.method}() command:
11
+ ${r}`)}}_checkForChanges(){a(({window:e})=>{let t=e.location.href;t!==this._lastUrl&&(this._referrer=this._lastUrl,this._lastUrl=t,this.page(t))})}_getContext(){return{environment:this._config.environment,device_id:this._sessionManager.getDeviceId(),distinct_id:this._sessionManager.getDistinctId(),anonymous_id:this._sessionManager.getAnonymousId(),session_id:this._sessionManager.getSessionId()}}_processEvent(e,t){switch(this._sessionManager.getTrackingConsent()){case o.GRANTED:this._sendEvent(e,t);break;case o.PENDING:case o.DISMISSED:this._queue.enqueue({type:"event",eventType:e,payload:t});break;case o.DENIED:break}}async _sendEvent(e,t){try{await this._requester.send(`/${e}`,t)}catch(r){pe(r)&&this._config.onError?.(r),me(r)&&r.errorCode==="environment-not-found"?this._logger.warnDev(`Environment "${this._config.environment}" not found. Please create this environment in your Altertable dashboard at ${he(`/environments/new?name=${this._config.environment}`)} before tracking events.`):_e(r)?this._logger.error("Network error while sending event",{error:r.message,cause:r.cause,eventType:e}):this._logger.error("Failed to send event",{error:r,eventType:e,payload:t})}}};var Z=new B;a(({window:n})=>{let e=n.Altertable;if(e&&Array.isArray(e))for(let t of e){let r=t[0],s=t.slice(1);Z[r](...s)}n.Altertable=Z});return $e(ze);})();
10
12
  //# sourceMappingURL=index.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/keyBuilder.ts","../src/constants.ts","../src/lib/error.ts","../src/lib/invariant.ts","../src/lib/link.ts","../src/lib/logger.ts","../src/lib/parseUrl.ts","../src/lib/queue.ts","../src/lib/isBeaconSupported.ts","../src/lib/requester.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/viewport.ts","../src/lib/runtimeContext.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/keyBuilder';\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_ANONYMOUS_ID = 'anonymous';\nexport const PREFIX_DEVICE_ID = 'device';\n\nconst MINUTE_IN_MS = 1_000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_QUEUE_SIZE = 1_000;\nexport const REQUEST_TIMEOUT_MS = 5_000;\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\n/**\n * Available tracking consent states.\n *\n * Use these constants to manage user consent for tracking and analytics.\n *\n * @property GRANTED User has granted consent for tracking\n * @property DENIED User has denied consent for tracking\n * @property PENDING User hasn't made a decision yet\n * @property DISMISSED User dismissed the consent prompt\n *\n * @example\n * ```javascript\n * import { altertable, TrackingConsent } from '@altertable/altertable-js';\n *\n * // Set tracking consent to granted\n * altertable.configure({\n * trackingConsent: TrackingConsent.GRANTED,\n * });\n *\n * // Check current consent state\n * const consent = altertable.getTrackingConsent();\n * if (consent === TrackingConsent.GRANTED) {\n * // Tracking is allowed\n * }\n * ```\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 { StringWithAutocomplete } from '../types';\n\nexport type ApiErrorCode = StringWithAutocomplete<'environment-not-found'>;\n\nexport interface ApiErrorResponse {\n error_code?: ApiErrorCode;\n message?: string;\n [key: string]: unknown;\n}\n\n/**\n * Base error class for Altertable SDK errors\n */\nexport class AltertableError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AltertableError';\n }\n}\n\n/**\n * Error thrown when an API request fails\n */\nexport class ApiError extends AltertableError {\n constructor(\n public status: number,\n public statusText: string,\n public errorCode?: ApiErrorCode,\n public details?: ApiErrorResponse,\n public requestContext?: {\n url: string;\n method: string;\n payload?: unknown;\n }\n ) {\n super(`HTTP ${status}: ${statusText}${errorCode ? ` (${errorCode})` : ''}`);\n this.name = 'ApiError';\n }\n}\n\n/**\n * Error thrown when a network request fails (timeout, connection error, etc.)\n */\nexport class NetworkError extends AltertableError {\n constructor(\n message: string,\n public cause?: unknown\n ) {\n super(message);\n this.name = 'NetworkError';\n }\n}\n\nexport function isAltertableError(error: unknown): error is AltertableError {\n return error instanceof AltertableError;\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError;\n}\n\nexport function isNetworkError(error: unknown): error is NetworkError {\n return error instanceof NetworkError;\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 throw new InvariantError(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n}\n\nclass InvariantError extends Error {\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, InvariantError.prototype);\n }\n}\n","export function dashboardUrl(path: string = '') {\n return `https://altertable.ai/dashboard${path}`;\n}\n","/* eslint-disable no-console */\n\nimport {\n PROPERTY_URL,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { AliasPayload, IdentifyPayload, TrackPayload } 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: TrackPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event === '$pageview' ? 'Page' : 'Track'\n );\n const [eventTitleLabel, eventTitleStyle] = createEventTitleElement(\n payload.event === '$pageview'\n ? String(payload.properties[PROPERTY_URL])\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 ${eventTitleLabel} %c[${environmentBadgeLabel}] %c${timestampLabel} %c${consentBadgeLabel}`,\n eventBadgeStyle,\n eventTitleStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabel, userLabelStyle] = createEventLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.distinct_id ?? 'Not set'\n );\n const [anonymousLabel, anonymousLabelStyle] =\n createEventLabelElement('Anonymous ID');\n const [anonymousValueLabel, anonymousValueStyle] = createValueElement(\n payload.anonymous_id ?? 'Not set'\n );\n const [sessionLabel, sessionLabelStyle] =\n createEventLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${anonymousLabel} %c${anonymousValueLabel}`,\n anonymousLabelStyle,\n anonymousValueStyle\n );\n console.log(\n `%c${sessionLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n logIdentify: (\n payload: IdentifyPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] =\n createEventBadgeElement('Identify');\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c ${payload.distinct_id} %c[${environmentBadgeLabel}] %c${consentBadgeLabel}`,\n eventBadgeStyle,\n 'font-weight: 600;',\n environmentBadgeStyle,\n consentBadgeStyle\n );\n\n const [distinctIdLabel, distinctIdLabelStyle] =\n createEventLabelElement('Distinct ID');\n const [distinctIdValueLabel, distinctIdValueStyle] = createValueElement(\n payload.distinct_id ?? 'Not set'\n );\n const [anonymousLabel, anonymousLabelStyle] =\n createEventLabelElement('Anonymous ID');\n const [anonymousalueLabel, anonymousValueStyle] = createValueElement(\n payload.anonymous_id ?? 'Not set'\n );\n\n console.log(\n `%c${distinctIdLabel} %c${distinctIdValueLabel}`,\n distinctIdLabelStyle,\n distinctIdValueStyle\n );\n console.log(\n `%c${anonymousLabel} %c${anonymousalueLabel}`,\n anonymousLabelStyle,\n anonymousValueStyle\n );\n console.table(payload.traits);\n console.groupEnd();\n },\n logAlias: (\n payload: AliasPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] =\n createEventBadgeElement('Alias');\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c ${payload.distinct_id} %c[${environmentBadgeLabel}] %c${consentBadgeLabel}`,\n eventBadgeStyle,\n 'font-weight: 600;',\n environmentBadgeStyle,\n consentBadgeStyle\n );\n\n const [distinctIdLabel, distinctIdLabelStyle] =\n createEventLabelElement('Distinct ID');\n const [distinctIdValueLabel, distinctIdValueStyle] = createValueElement(\n payload.distinct_id ?? 'Not set'\n );\n\n const [newUserIdLabel, newUserIdLabelStyle] =\n createEventLabelElement('New User ID');\n const [newUserIdValueLabel, newUserIdValueStyle] = createValueElement(\n payload.new_user_id ?? 'Not set'\n );\n\n console.log(\n `%c${distinctIdLabel} %c${distinctIdValueLabel}`,\n distinctIdLabelStyle,\n distinctIdValueStyle\n );\n console.log(\n `%c${newUserIdLabel} %c${newUserIdValueLabel}`,\n newUserIdLabelStyle,\n newUserIdValueStyle\n );\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 getEventBadgeColor(event: string) {\n switch (event) {\n case 'Page':\n return '#64748b';\n case 'Identify':\n return '#a855f7';\n case 'Track':\n return '#10b981';\n default:\n return '#1e293b';\n }\n}\n\nfunction createEventBadgeElement(event: string): [string, string] {\n return [\n event,\n `background: ${getEventBadgeColor(event)}; color: #ffffff; padding: 2px 8px; border-radius: 6px; font-weight: 400;`,\n ];\n}\n\nfunction createEventTitleElement(event: string): [string, string] {\n const label = event === '$pageview' ? 'Page Viewed' : event;\n return [label, 'font-weight: 600;'];\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 createEventLabelElement(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","type ParsedUrl = {\n baseUrl: string;\n searchParams: Record<string, string>;\n};\n\nexport function parseUrl(url: string): ParsedUrl | null {\n try {\n const parsedUrl = new URL(url);\n return {\n baseUrl: `${parsedUrl.origin}${parsedUrl.pathname}`,\n searchParams: Object.fromEntries(parsedUrl.searchParams),\n };\n } catch {\n return null;\n }\n}\n","interface QueueOptions<TItem> {\n capacity: number;\n onDropOldest?: (command: TItem) => void;\n}\n\nexport class Queue<TItem> {\n private _items: TItem[] = [];\n private _maxSize: number;\n private _onDropOldest?: (command: TItem) => void;\n\n constructor(options: QueueOptions<TItem>) {\n this._maxSize = options.capacity;\n this._onDropOldest = options.onDropOldest;\n }\n\n enqueue(command: TItem): void {\n if (this._items.length >= this._maxSize) {\n const dropped = this._items.shift();\n if (dropped) {\n this._onDropOldest?.(dropped);\n }\n }\n this._items.push(command);\n }\n\n flush(): TItem[] {\n const items = [...this._items];\n this._items = [];\n return items;\n }\n\n clear(): void {\n this._items = [];\n }\n\n /** @internal */\n getSize(): number {\n return this._items.length;\n }\n\n /** @internal */\n getAll(): readonly TItem[] {\n return this._items;\n }\n}\n","export function isBeaconSupported(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n typeof navigator.sendBeacon === 'function'\n );\n}\n","import { EventPayload } from '../types';\nimport { ApiError, ApiErrorResponse, NetworkError } from './error';\nimport { isBeaconSupported } from './isBeaconSupported';\n\nexport interface RequesterConfig {\n baseUrl: string;\n apiKey: string;\n requestTimeout: number;\n}\n\nexport class Requester<TPayload extends EventPayload> {\n private readonly _config: Required<RequesterConfig>;\n\n constructor(config: RequesterConfig) {\n this._config = config;\n }\n\n private _constructUrl(path: string): string {\n return `${this._config.baseUrl}${path}?apiKey=${encodeURIComponent(\n this._config.apiKey\n )}`;\n }\n\n async send(path: string, payload: TPayload): Promise<void> {\n if (isBeaconSupported()) {\n return this._sendWithBeacon(path, payload);\n }\n\n return this._sendWithFetch(path, payload);\n }\n\n private async _sendWithBeacon(\n path: string,\n payload: TPayload\n ): Promise<void> {\n const url = this._constructUrl(path);\n const data = new Blob([JSON.stringify(payload)], {\n type: 'application/json',\n });\n\n try {\n const success = navigator.sendBeacon(url, data);\n if (!success) {\n return this._sendWithFetch(path, payload);\n }\n } catch (error) {\n return this._sendWithFetch(path, payload);\n }\n }\n\n private async _sendWithFetch(path: string, payload: TPayload): Promise<void> {\n const url = this._constructUrl(path);\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n this._config.requestTimeout\n );\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n keepalive: true,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n let errorResponse: ApiErrorResponse | undefined;\n\n try {\n errorResponse = await response.json();\n } catch {\n // If parsing fails, continue without parsed response\n }\n\n throw new ApiError(\n response.status,\n response.statusText,\n errorResponse?.error_code,\n errorResponse,\n {\n url,\n method: 'POST',\n payload,\n }\n );\n }\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n\n throw new NetworkError(\n error instanceof Error ? error.message : 'Network request failed',\n error\n );\n } finally {\n clearTimeout(timeoutId);\n }\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 type PropertyViewport = string | null;\n\nexport function getViewport(): PropertyViewport {\n return safelyRunOnBrowser<PropertyViewport>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\nimport { getViewport, PropertyViewport } from './viewport';\n\n/**\n * Runtime context captured at event time.\n *\n * This is used for events that need browser state (URL, viewport, referrer)\n * prior to the library being initialized. It ensures that the event payload\n * reflects the correct time-sensitive data from when the user called the method,\n * not when the queue is flushed post-init.\n */\nexport type RuntimeContext = {\n timestamp: string;\n url: PropertyUrl;\n referrer: PropertyReferrer;\n viewport: PropertyViewport;\n};\ntype PropertyReferrer = string | null;\ntype PropertyUrl = string | null;\n\nexport function captureRuntimeContext(): RuntimeContext {\n return {\n timestamp: new Date().toISOString(),\n url: safelyRunOnBrowser<PropertyUrl>(\n ({ window }) => window.location.href || null,\n () => null\n ),\n referrer: safelyRunOnBrowser<PropertyReferrer>(\n ({ window }) => window.document.referrer || null,\n () => null\n ),\n viewport: getViewport(),\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_ANONYMOUS_ID,\n PREFIX_DEVICE_ID,\n PREFIX_SESSION_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport type {\n AnonymousId,\n DeviceId,\n DistinctId,\n SessionId,\n UserId,\n} from '../types';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\n\ntype SessionData = {\n deviceId: DeviceId;\n distinctId: DistinctId;\n anonymousId: AnonymousId | null;\n sessionId: SessionId;\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 deviceId: parsedData.deviceId || this._generateDeviceId(),\n distinctId: parsedData.distinctId || this._generateAnonymousId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n anonymousId: parsedData.anonymousId || 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 getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getDeviceId(): DeviceId {\n return this._sessionData.deviceId;\n }\n\n getDistinctId(): DistinctId {\n return this._sessionData.distinctId;\n }\n\n getAnonymousId(): AnonymousId | null {\n return this._sessionData.anonymousId;\n }\n\n /**\n * Returns whether the current user is identified.\n *\n * The `anonymousId` field is a \"before\" snapshot: if set, the user was previously\n * anonymous and is now identified. If `null`, the user is still anonymous.\n *\n * When transitioning from anonymous to identified, we preserve the anonymous ID\n * to enable identity merging on the backend. This allows:\n * - Linking pre-identification events (anonymous ID) to post-identification events (user ID)\n * - Merging user profiles so anonymous browsing behavior is associated with the identified user\n * - Maintaining a complete user journey from first visit through identification\n *\n * **State Transitions:**\n * - **Anonymous:** `anonymousId = null`, `distinctId = anonymousId`, `isIdentified() = false`\n * - **Identified:** `anonymousId = previous distinctId`, `distinctId = userId`, `isIdentified() = true`\n */\n isIdentified(): boolean {\n return Boolean(this._sessionData.anonymousId);\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n identify(userId: UserId): void {\n this._sessionData.anonymousId = this._sessionData.distinctId as AnonymousId;\n this._sessionData.distinctId = 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 resetDeviceId = false,\n resetTrackingConsent = false,\n }: {\n resetDeviceId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetDeviceId) {\n this._sessionData.deviceId = this._generateDeviceId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.anonymousId = null;\n this._sessionData.distinctId = this._generateAnonymousId();\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n anonymousId: null,\n deviceId: this._generateDeviceId(),\n distinctId: this._generateAnonymousId(),\n lastEventAt: null,\n sessionId: this._generateSessionId(),\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateDeviceId(): DeviceId {\n return generateId(PREFIX_DEVICE_ID);\n }\n\n private _generateAnonymousId(): AnonymousId {\n return generateId(PREFIX_ANONYMOUS_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 EVENT_PAGEVIEW,\n keyBuilder,\n MAX_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n REQUEST_TIMEOUT_MS,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { isAltertableError, isApiError, isNetworkError } from './lib/error';\nimport { invariant } from './lib/invariant';\nimport { dashboardUrl } from './lib/link';\nimport { createLogger } from './lib/logger';\nimport { parseUrl } from './lib/parseUrl';\nimport { Queue } from './lib/queue';\nimport { Requester } from './lib/requester';\nimport { captureRuntimeContext, RuntimeContext } from './lib/runtimeContext';\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 { getViewport } from './lib/viewport';\nimport {\n AliasPayload,\n AltertableContext,\n DistinctId,\n Environment,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n TrackPayload,\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?: Environment;\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 \"granted\"\n */\n trackingConsent?: TrackingConsentType;\n /**\n * Optional error handler for intercepting SDK errors.\n */\n onError?: (error: Error) => void;\n}\n\nconst DEFAULT_CONFIG: AltertableConfig = {\n autoCapture: true,\n baseUrl: 'https://api.altertable.ai',\n debug: false,\n environment: 'production',\n persistence: 'localStorage+cookie',\n release: undefined,\n trackingConsent: TrackingConsent.GRANTED,\n};\n\nexport class Altertable {\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _queue: Queue<QueueItem>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _requester: Requester<EventPayload> | undefined;\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._queue = new Queue<QueueItem>({\n capacity: MAX_QUEUE_SIZE,\n onDropOldest: droppedItem => {\n const method =\n droppedItem.type === 'command'\n ? droppedItem.method\n : droppedItem.eventType;\n this._logger.warnDev(\n `Queue is full (${MAX_QUEUE_SIZE} items). Dropping ${method} call.`\n );\n },\n });\n }\n\n /**\n * Initializes the Altertable SDK with your API key and optional configuration.\n *\n * @param apiKey Your Altertable API key\n * @param config Configuration options\n * @returns A cleanup function to remove event listeners\n *\n * @example\n * ```javascript\n * altertable.init('YOUR_API_KEY', {\n * environment: 'development',\n * });\n * ```\n */\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._config = { ...DEFAULT_CONFIG, ...config };\n this._storageKey = keyBuilder(apiKey, this._config.environment);\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 this._storage = selectStorage(this._config.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._requester = new Requester({\n baseUrl: this._config.baseUrl,\n apiKey,\n requestTimeout: REQUEST_TIMEOUT_MS,\n });\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: this._config.trackingConsent,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n const trackingConsent = this._sessionManager.getTrackingConsent();\n if (trackingConsent === TrackingConsent.GRANTED) {\n this._flushQueue();\n } else if (trackingConsent === TrackingConsent.DENIED) {\n this._queue.clear();\n }\n\n this._handleAutoCaptureChange(this._config.autoCapture);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n /**\n * Updates the configuration after initialization.\n *\n * @param updates Configuration updates to apply\n *\n * @example\n * ```javascript\n * altertable.configure({\n * trackingConsent: 'granted',\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 this._flushQueue();\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._queue.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 /**\n * Identifies a user with their ID and optional traits.\n *\n * Notes:\n * - You can call this method multiple times with the same ID.\n * - To change traits, use {@link updateTraits} instead.\n * - To switch to a new user ID, call {@link reset} first.\n *\n * @param userId The user's unique identifier\n * @param traits User properties\n *\n * @example\n * ```javascript\n * altertable.identify('u_01jza857w4f23s1hf2s61befmw', {\n * email: 'john.doe@example.com',\n * name: 'John Doe',\n * company: 'Acme Corp',\n * role: 'Software Engineer',\n * });\n * ```\n */\n identify(userId: DistinctId, traits: UserTraits = {}) {\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'identify',\n args: [userId, { ...traits }],\n });\n return;\n }\n\n this._identify(userId, { ...traits });\n }\n\n private _identify(userId: DistinctId, traits: UserTraits = {}) {\n invariant(\n !this._sessionManager.isIdentified() ||\n userId === this._sessionManager.getDistinctId(),\n `User (${userId}) is already identified as a different user (${this._sessionManager.getDistinctId()}). This usually indicates a development issue, as it would merge two separate identities. Call reset() before identifying a new user, or use alias() to link the new ID to the existing one.`\n );\n\n if (userId !== this._sessionManager.getDistinctId()) {\n this._sessionManager.identify(userId);\n }\n\n const context = this._getContext();\n const payload: IdentifyPayload = {\n environment: context.environment,\n device_id: context.device_id,\n distinct_id: context.distinct_id,\n traits,\n anonymous_id: context.anonymous_id,\n };\n this._processEvent('identify', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logIdentify(payload, { trackingConsent });\n }\n }\n\n /**\n * Link a new ID to the current identity.\n *\n * @param newUserId The new user ID\n *\n * @example\n * ```javascript\n * altertable.alias('u_01jza857w4f23s1hf2s61befmw');\n * ```\n */\n alias(newUserId: DistinctId) {\n try {\n validateUserId(newUserId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'alias',\n args: [newUserId],\n });\n return;\n }\n\n this._alias(newUserId);\n }\n\n private _alias(newUserId: DistinctId) {\n const context = this._getContext();\n\n const payload: AliasPayload = {\n environment: context.environment,\n device_id: context.device_id,\n anonymous_id: context.anonymous_id,\n distinct_id: context.distinct_id,\n new_user_id: newUserId,\n };\n\n this._processEvent('alias', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logAlias(payload, { trackingConsent });\n }\n }\n\n /**\n * Updates user traits for the current user.\n *\n * @param traits User properties to update\n *\n * @example\n * ```javascript\n * altertable.updateTraits({\n * onboarding_completed: true,\n * });\n * ```\n */\n updateTraits(traits: UserTraits) {\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'updateTraits',\n args: [{ ...traits }],\n });\n return;\n }\n\n this._updateTraits({ ...traits });\n }\n\n private _updateTraits(traits: UserTraits) {\n const context = this._getContext();\n\n invariant(\n context.anonymous_id !== null,\n 'User must be identified with identify() before updating traits.'\n );\n\n const payload = {\n environment: context.environment,\n device_id: context.device_id,\n distinct_id: context.distinct_id,\n traits,\n anonymous_id: context.anonymous_id,\n session_id: context.session_id,\n };\n this._processEvent('identify', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logIdentify(payload, { trackingConsent });\n }\n }\n\n /**\n * Resets device and session IDs.\n *\n * @example\n * ```javascript\n * // Reset session, user and visitor (default)\n * altertable.reset();\n *\n * // Reset session, user, visitor and device\n * altertable.reset({\n * resetDeviceId: true,\n * });\n * ```\n */\n reset({\n resetDeviceId = false,\n }: {\n /** Whether to reset device ID (default: false) */\n resetDeviceId?: boolean;\n } = {}) {\n // Clear queued commands to prevent cross-identity/session mixing\n this._queue.clear();\n\n if (!this._isInitialized) {\n return;\n }\n\n this._sessionManager.reset({\n resetDeviceId,\n });\n }\n\n /**\n * Tracks a page view event.\n *\n * When `autoCapture` is enabled (default), this method is automatically called when the page URL changes.\n *\n * @param url The page URL\n *\n * @example\n * ```javascript\n * altertable.page('https://example.com/products');\n * ```\n *\n * @remarks\n * **Page Tracking**: By default, Altertable automatically captures page views. Only use `page()` when you've disabled auto-capture.\n *\n * **Why use auto-capture (default)?**\n * - No manual tracking required\n * - Handles browser navigation events (popstate, hashchange)\n * - Consistent tracking across all page changes\n *\n * **When to use `page()`:**\n * - Custom routing that doesn't trigger browser events\n * - Virtual page views that don't trigger URL changes (modals, step changes)\n * - Server-side tracking where auto-capture isn't available\n */\n page(url: string) {\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'page',\n runtimeContext: captureRuntimeContext(),\n args: [url],\n });\n return;\n }\n\n this._page(url);\n }\n\n private _page(url: string, runtimeContext?: RuntimeContext) {\n const parsedUrl = parseUrl(url);\n const baseUrl = parsedUrl ? parsedUrl.baseUrl : url;\n\n const viewport = runtimeContext?.viewport ?? getViewport();\n const referrer = runtimeContext?.referrer ?? this._referrer;\n\n this._track(\n EVENT_PAGEVIEW,\n {\n [PROPERTY_URL]: baseUrl,\n [PROPERTY_VIEWPORT]: viewport,\n [PROPERTY_REFERER]: referrer,\n ...parsedUrl?.searchParams,\n },\n runtimeContext\n );\n }\n\n /**\n * Tracks a custom event with optional properties.\n *\n * @param eventThe event name\n * @param properties Custom event properties\n *\n * @example\n * ```javascript\n * altertable.track('Purchase Completed', {\n * product_id: 'p_01jza8fr5efvgbxxdd1bwkd0m5',\n * amount: 29.99,\n * currency: 'USD',\n * });\n * ```\n */\n track(event: string, properties: EventProperties = {}) {\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'track',\n runtimeContext: captureRuntimeContext(),\n args: [event, { ...properties }],\n });\n return;\n }\n\n this._track(event, { ...properties });\n }\n\n private _track(\n event: string,\n properties: EventProperties,\n runtimeContext: RuntimeContext = captureRuntimeContext()\n ) {\n this._sessionManager.renewSessionIfNeeded();\n this._sessionManager.updateLastEventAt(runtimeContext.timestamp);\n\n const context = this._getContext();\n\n // Strip undefined $url to prevent it from overriding computed URL\n const { [PROPERTY_URL]: userUrl, ...restProperties } = properties;\n const hasUrl = userUrl !== undefined;\n const urlForEvent = hasUrl ? null : runtimeContext.url;\n\n const parsedUrl = urlForEvent ? parseUrl(urlForEvent) : null;\n const baseUrl = parsedUrl ? parsedUrl.baseUrl : urlForEvent;\n\n const payload: TrackPayload = {\n timestamp: runtimeContext.timestamp,\n event,\n environment: context.environment,\n device_id: context.device_id,\n distinct_id: context.distinct_id,\n anonymous_id: context.anonymous_id,\n session_id: context.session_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n [PROPERTY_URL]: hasUrl ? userUrl : baseUrl,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...restProperties,\n },\n };\n\n this._processEvent('track', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n /**\n * Returns the current tracking consent state.\n *\n * @returns The current tracking consent state\n * @see {@link TrackingConsent}\n *\n * @example\n * ```javascript\n * const consent = altertable.getTrackingConsent();\n * if (consent === 'granted') {\n * // Tracking is allowed\n * }\n * ```\n */\n getTrackingConsent(): TrackingConsentType {\n if (!this._isInitialized) {\n return TrackingConsent.PENDING;\n }\n return this._sessionManager.getTrackingConsent();\n }\n\n private _flushQueue() {\n const items = this._queue.flush();\n\n if (items.length === 0) {\n return;\n }\n\n if (this._config.debug) {\n this._logger.log(\n `Processing ${items.length} queued ${items.length === 1 ? 'item' : 'items'}.`\n );\n }\n\n for (const item of items) {\n this._executeQueueItem(item);\n }\n }\n\n private _executeQueueItem(item: QueueItem) {\n if (item.type === 'event') {\n // Send pre-built payload directly (preserves original session context)\n this._sendEvent(item.eventType, item.payload);\n return;\n }\n // Execute command (pre-init path)\n this._executeCommand(item);\n }\n\n private _executeCommand(cmd: QueuedCommand) {\n try {\n switch (cmd.method) {\n case 'identify':\n this._identify(...cmd.args);\n break;\n case 'track':\n this._track(...cmd.args, cmd.runtimeContext);\n break;\n case 'page':\n this._page(...cmd.args, cmd.runtimeContext);\n break;\n case 'alias':\n this._alias(...cmd.args);\n break;\n case 'updateTraits':\n this._updateTraits(...cmd.args);\n break;\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n this._logger.warnDev(\n `Failed to process queued ${cmd.method}() command:\\n${errorMessage}`\n );\n }\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n this.page(currentUrl);\n }\n });\n }\n\n private _getContext(): AltertableContext {\n return {\n environment: this._config.environment,\n device_id: this._sessionManager.getDeviceId(),\n distinct_id: this._sessionManager.getDistinctId(),\n anonymous_id: this._sessionManager.getAnonymousId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload>(\n eventType: EventType,\n payload: TPayload\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._sendEvent(eventType, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._queue.enqueue({\n type: 'event',\n eventType,\n payload,\n });\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private async _sendEvent<TPayload extends EventPayload>(\n eventType: EventType,\n payload: TPayload\n ) {\n try {\n await this._requester.send(`/${eventType}`, payload);\n } catch (error) {\n if (isAltertableError(error)) {\n this._config.onError?.(error);\n }\n\n if (isApiError(error) && error.errorCode === 'environment-not-found') {\n this._logger.warnDev(\n `Environment \"${this._config.environment}\" not found. Please create this environment in your Altertable dashboard at ${dashboardUrl(`/environments/new?name=${this._config.environment}`)} before tracking events.`\n );\n } else if (isNetworkError(error)) {\n this._logger.error('Network error while sending event', {\n error: error.message,\n cause: error.cause,\n eventType,\n });\n } else {\n this._logger.error('Failed to send event', {\n error,\n eventType,\n payload,\n });\n }\n }\n }\n}\n\ntype QueuedCommand =\n | {\n type: 'command';\n method: 'identify';\n args: Parameters<Altertable['identify']>;\n }\n | {\n type: 'command';\n method: 'track';\n args: Parameters<Altertable['track']>;\n runtimeContext: RuntimeContext;\n }\n | {\n type: 'command';\n method: 'page';\n args: Parameters<Altertable['page']>;\n runtimeContext: RuntimeContext;\n }\n | {\n type: 'command';\n method: 'alias';\n args: Parameters<Altertable['alias']>;\n }\n | {\n type: 'command';\n method: 'updateTraits';\n args: Parameters<Altertable['updateTraits']>;\n };\n\ntype QueuedEvent = {\n type: 'event';\n eventType: EventType;\n payload: EventPayload;\n};\n\ntype QueueItem = QueuedCommand | QueuedEvent;\n"],"mappings":"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","names":["index_exports","__export","TrackingConsent","altertable","createKeyBuilder","prefix","separator","parts","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_ANONYMOUS_ID","PREFIX_DEVICE_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_QUEUE_SIZE","REQUEST_TIMEOUT_MS","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","AltertableError","message","ApiError","status","statusText","errorCode","details","requestContext","NetworkError","cause","isAltertableError","error","isApiError","isNetworkError","invariant","condition","message","InvariantError","_InvariantError","dashboardUrl","path","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","eventTitleLabel","eventTitleStyle","createEventTitleElement","PROPERTY_URL","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabel","userLabelStyle","createEventLabelElement","userValueLabel","userValueStyle","createValueElement","anonymousLabel","anonymousLabelStyle","anonymousValueLabel","anonymousValueStyle","sessionLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","distinctIdLabel","distinctIdLabelStyle","distinctIdValueLabel","distinctIdValueStyle","anonymousalueLabel","newUserIdLabel","newUserIdLabelStyle","newUserIdValueLabel","newUserIdValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","getEventBadgeColor","event","value","getEnvironmentColor","environment","TrackingConsent","parseUrl","url","parsedUrl","Queue","options","command","dropped","items","isBeaconSupported","Requester","config","path","payload","isBeaconSupported","url","data","controller","timeoutId","response","errorResponse","ApiError","error","NetworkError","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","captureRuntimeContext","safelyRunOnBrowser","window","getViewport","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetDeviceId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_DEVICE_ID","PREFIX_ANONYMOUS_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","DEFAULT_CONFIG","TrackingConsent","Altertable","createLogger","Queue","MAX_QUEUE_SIZE","droppedItem","method","apiKey","config","invariant","keyBuilder","safelyRunOnBrowser","window","selectStorage","message","Requester","REQUEST_TIMEOUT_MS","SessionManager","trackingConsent","updates","previousStorage","currentTrackingConsent","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","payload","newUserId","resetDeviceId","url","captureRuntimeContext","runtimeContext","parsedUrl","parseUrl","baseUrl","viewport","getViewport","referrer","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","PROPERTY_REFERER","event","properties","userUrl","restProperties","hasUrl","urlForEvent","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","items","item","cmd","errorMessage","currentUrl","eventType","isAltertableError","isApiError","dashboardUrl","isNetworkError","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/keyBuilder.ts","../src/constants.ts","../src/lib/error.ts","../src/lib/invariant.ts","../src/lib/link.ts","../src/lib/logger.ts","../src/lib/parseUrl.ts","../src/lib/queue.ts","../src/lib/isBeaconSupported.ts","../src/lib/requester.ts","../src/lib/safelyRunOnBrowser.ts","../src/lib/viewport.ts","../src/lib/runtimeContext.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/keyBuilder';\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_ANONYMOUS_ID = 'anonymous';\nexport const PREFIX_DEVICE_ID = 'device';\n\nconst MINUTE_IN_MS = 1_000 * 60;\nexport const AUTO_CAPTURE_INTERVAL_MS = 100;\nexport const SESSION_EXPIRATION_TIME_MS = 30 * MINUTE_IN_MS;\nexport const MAX_QUEUE_SIZE = 1_000;\nexport const REQUEST_TIMEOUT_MS = 5_000;\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\n/**\n * Available tracking consent states.\n *\n * Use these constants to manage user consent for tracking and analytics.\n *\n * @property GRANTED User has granted consent for tracking\n * @property DENIED User has denied consent for tracking\n * @property PENDING User hasn't made a decision yet\n * @property DISMISSED User dismissed the consent prompt\n *\n * @example\n * ```javascript\n * import { altertable, TrackingConsent } from '@altertable/altertable-js';\n *\n * // Set tracking consent to granted\n * altertable.configure({\n * trackingConsent: TrackingConsent.GRANTED,\n * });\n *\n * // Check current consent state\n * const consent = altertable.getTrackingConsent();\n * if (consent === TrackingConsent.GRANTED) {\n * // Tracking is allowed\n * }\n * ```\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 { StringWithAutocomplete } from '../types';\n\nexport type ApiErrorCode = StringWithAutocomplete<'environment-not-found'>;\n\nexport interface ApiErrorResponse {\n error_code?: ApiErrorCode;\n message?: string;\n [key: string]: unknown;\n}\n\n/**\n * Base error class for Altertable SDK errors\n */\nexport class AltertableError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AltertableError';\n }\n}\n\n/**\n * Error thrown when an API request fails\n */\nexport class ApiError extends AltertableError {\n constructor(\n public status: number,\n public statusText: string,\n public errorCode?: ApiErrorCode,\n public details?: ApiErrorResponse,\n public requestContext?: {\n url: string;\n method: string;\n payload?: unknown;\n }\n ) {\n super(`HTTP ${status}: ${statusText}${errorCode ? ` (${errorCode})` : ''}`);\n this.name = 'ApiError';\n }\n}\n\n/**\n * Error thrown when a network request fails (timeout, connection error, etc.)\n */\nexport class NetworkError extends AltertableError {\n constructor(\n message: string,\n public cause?: unknown\n ) {\n super(message);\n this.name = 'NetworkError';\n }\n}\n\nexport function isAltertableError(error: unknown): error is AltertableError {\n return error instanceof AltertableError;\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError;\n}\n\nexport function isNetworkError(error: unknown): error is NetworkError {\n return error instanceof NetworkError;\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 throw new InvariantError(\n `[Altertable] ${typeof message === 'function' ? message() : message}`\n );\n}\n\nclass InvariantError extends Error {\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, InvariantError.prototype);\n }\n}\n","export function dashboardUrl(path: string = '') {\n return `https://altertable.ai/dashboard${path}`;\n}\n","/* eslint-disable no-console */\n\nimport {\n PROPERTY_URL,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport { AliasPayload, IdentifyPayload, TrackPayload } 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: TrackPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] = createEventBadgeElement(\n payload.event === '$pageview' ? 'Page' : 'Track'\n );\n const [eventTitleLabel, eventTitleStyle] = createEventTitleElement(\n payload.event === '$pageview'\n ? String(payload.properties[PROPERTY_URL])\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 ${eventTitleLabel} %c[${environmentBadgeLabel}] %c${timestampLabel} %c${consentBadgeLabel}`,\n eventBadgeStyle,\n eventTitleStyle,\n environmentBadgeStyle,\n timestampStyle,\n consentBadgeStyle\n );\n\n const [userLabel, userLabelStyle] = createEventLabelElement('User ID');\n const [userValueLabel, userValueStyle] = createValueElement(\n payload.distinct_id ?? 'Not set'\n );\n const [anonymousLabel, anonymousLabelStyle] =\n createEventLabelElement('Anonymous ID');\n const [anonymousValueLabel, anonymousValueStyle] = createValueElement(\n payload.anonymous_id ?? 'Not set'\n );\n const [sessionLabel, sessionLabelStyle] =\n createEventLabelElement('Session ID');\n const [sessionValueLabel, sessionValueStyle] = createValueElement(\n payload.session_id ?? 'Not set'\n );\n\n console.log(\n `%c${userLabel} %c${userValueLabel}`,\n userLabelStyle,\n userValueStyle\n );\n console.log(\n `%c${anonymousLabel} %c${anonymousValueLabel}`,\n anonymousLabelStyle,\n anonymousValueStyle\n );\n console.log(\n `%c${sessionLabel} %c${sessionValueLabel}`,\n sessionLabelStyle,\n sessionValueStyle\n );\n console.table(payload.properties);\n console.groupEnd();\n },\n logIdentify: (\n payload: IdentifyPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] =\n createEventBadgeElement('Identify');\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c ${payload.distinct_id} %c[${environmentBadgeLabel}] %c${consentBadgeLabel}`,\n eventBadgeStyle,\n 'font-weight: 600;',\n environmentBadgeStyle,\n consentBadgeStyle\n );\n\n const [distinctIdLabel, distinctIdLabelStyle] =\n createEventLabelElement('Distinct ID');\n const [distinctIdValueLabel, distinctIdValueStyle] = createValueElement(\n payload.distinct_id ?? 'Not set'\n );\n const [anonymousLabel, anonymousLabelStyle] =\n createEventLabelElement('Anonymous ID');\n const [anonymousalueLabel, anonymousValueStyle] = createValueElement(\n payload.anonymous_id ?? 'Not set'\n );\n\n console.log(\n `%c${distinctIdLabel} %c${distinctIdValueLabel}`,\n distinctIdLabelStyle,\n distinctIdValueStyle\n );\n console.log(\n `%c${anonymousLabel} %c${anonymousalueLabel}`,\n anonymousLabelStyle,\n anonymousValueStyle\n );\n console.table(payload.traits);\n console.groupEnd();\n },\n logAlias: (\n payload: AliasPayload,\n { trackingConsent }: { trackingConsent: TrackingConsentType }\n ) => {\n const [eventBadgeLabel, eventBadgeStyle] =\n createEventBadgeElement('Alias');\n const [environmentBadgeLabel, environmentBadgeStyle] =\n createEnvironmentBadgeElement(payload.environment);\n const [consentBadgeLabel, consentBadgeStyle] =\n getConsentBadgeElement(trackingConsent);\n\n console.groupCollapsed(\n `[${prefix}] %c${eventBadgeLabel}%c ${payload.distinct_id} %c[${environmentBadgeLabel}] %c${consentBadgeLabel}`,\n eventBadgeStyle,\n 'font-weight: 600;',\n environmentBadgeStyle,\n consentBadgeStyle\n );\n\n const [distinctIdLabel, distinctIdLabelStyle] =\n createEventLabelElement('Distinct ID');\n const [distinctIdValueLabel, distinctIdValueStyle] = createValueElement(\n payload.distinct_id ?? 'Not set'\n );\n\n const [newUserIdLabel, newUserIdLabelStyle] =\n createEventLabelElement('New User ID');\n const [newUserIdValueLabel, newUserIdValueStyle] = createValueElement(\n payload.new_user_id ?? 'Not set'\n );\n\n console.log(\n `%c${distinctIdLabel} %c${distinctIdValueLabel}`,\n distinctIdLabelStyle,\n distinctIdValueStyle\n );\n console.log(\n `%c${newUserIdLabel} %c${newUserIdValueLabel}`,\n newUserIdLabelStyle,\n newUserIdValueStyle\n );\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 getEventBadgeColor(event: string) {\n switch (event) {\n case 'Page':\n return '#64748b';\n case 'Identify':\n return '#a855f7';\n case 'Track':\n return '#10b981';\n default:\n return '#1e293b';\n }\n}\n\nfunction createEventBadgeElement(event: string): [string, string] {\n return [\n event,\n `background: ${getEventBadgeColor(event)}; color: #ffffff; padding: 2px 8px; border-radius: 6px; font-weight: 400;`,\n ];\n}\n\nfunction createEventTitleElement(event: string): [string, string] {\n const label = event === '$pageview' ? 'Page Viewed' : event;\n return [label, 'font-weight: 600;'];\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 createEventLabelElement(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","type ParsedUrl = {\n baseUrl: string;\n searchParams: Record<string, string>;\n};\n\nexport function parseUrl(url: string): ParsedUrl | null {\n try {\n const parsedUrl = new URL(url);\n return {\n baseUrl: `${parsedUrl.origin}${parsedUrl.pathname}`,\n searchParams: Object.fromEntries(parsedUrl.searchParams),\n };\n } catch {\n return null;\n }\n}\n","interface QueueOptions<TItem> {\n capacity: number;\n onDropOldest?: (command: TItem) => void;\n}\n\nexport class Queue<TItem> {\n private _items: TItem[] = [];\n private _maxSize: number;\n private _onDropOldest?: (command: TItem) => void;\n\n constructor(options: QueueOptions<TItem>) {\n this._maxSize = options.capacity;\n this._onDropOldest = options.onDropOldest;\n }\n\n enqueue(command: TItem): void {\n if (this._items.length >= this._maxSize) {\n const dropped = this._items.shift();\n if (dropped) {\n this._onDropOldest?.(dropped);\n }\n }\n this._items.push(command);\n }\n\n flush(): TItem[] {\n const items = [...this._items];\n this._items = [];\n return items;\n }\n\n clear(): void {\n this._items = [];\n }\n\n /** @internal */\n getSize(): number {\n return this._items.length;\n }\n\n /** @internal */\n getAll(): readonly TItem[] {\n return this._items;\n }\n}\n","export function isBeaconSupported(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n typeof navigator.sendBeacon === 'function'\n );\n}\n","import { EventPayload } from '../types';\nimport { ApiError, ApiErrorResponse, NetworkError } from './error';\nimport { isBeaconSupported } from './isBeaconSupported';\n\nexport interface RequesterConfig {\n baseUrl: string;\n apiKey: string;\n requestTimeout: number;\n}\n\nexport class Requester<TPayload extends EventPayload> {\n private readonly _config: Required<RequesterConfig>;\n\n constructor(config: RequesterConfig) {\n this._config = config;\n }\n\n private _constructUrl(path: string): string {\n return `${this._config.baseUrl}${path}?apiKey=${encodeURIComponent(\n this._config.apiKey\n )}`;\n }\n\n async send(path: string, payload: TPayload): Promise<void> {\n if (isBeaconSupported()) {\n return this._sendWithBeacon(path, payload);\n }\n\n return this._sendWithFetch(path, payload);\n }\n\n private async _sendWithBeacon(\n path: string,\n payload: TPayload\n ): Promise<void> {\n const url = this._constructUrl(path);\n const data = new Blob([JSON.stringify(payload)], {\n type: 'application/json',\n });\n\n try {\n const success = navigator.sendBeacon(url, data);\n if (!success) {\n return this._sendWithFetch(path, payload);\n }\n } catch (error) {\n return this._sendWithFetch(path, payload);\n }\n }\n\n private async _sendWithFetch(path: string, payload: TPayload): Promise<void> {\n const url = this._constructUrl(path);\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n this._config.requestTimeout\n );\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n keepalive: true,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n let errorResponse: ApiErrorResponse | undefined;\n\n try {\n errorResponse = await response.json();\n } catch {\n // If parsing fails, continue without parsed response\n }\n\n throw new ApiError(\n response.status,\n response.statusText,\n errorResponse?.error_code,\n errorResponse,\n {\n url,\n method: 'POST',\n payload,\n }\n );\n }\n } catch (error) {\n if (error instanceof ApiError) {\n throw error;\n }\n\n throw new NetworkError(\n error instanceof Error ? error.message : 'Network request failed',\n error\n );\n } finally {\n clearTimeout(timeoutId);\n }\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 type PropertyViewport = string | null;\n\nexport function getViewport(): PropertyViewport {\n return safelyRunOnBrowser<PropertyViewport>(\n ({ window }) => `${window.innerWidth}x${window.innerHeight}`,\n () => null\n );\n}\n","import { safelyRunOnBrowser } from './safelyRunOnBrowser';\nimport { getViewport, PropertyViewport } from './viewport';\n\n/**\n * Runtime context captured at event time.\n *\n * This is used for events that need browser state (URL, viewport, referrer)\n * prior to the library being initialized. It ensures that the event payload\n * reflects the correct time-sensitive data from when the user called the method,\n * not when the queue is flushed post-init.\n */\nexport type RuntimeContext = {\n timestamp: string;\n url: PropertyUrl;\n referrer: PropertyReferrer;\n viewport: PropertyViewport;\n};\ntype PropertyReferrer = string | null;\ntype PropertyUrl = string | null;\n\nexport function captureRuntimeContext(): RuntimeContext {\n return {\n timestamp: new Date().toISOString(),\n url: safelyRunOnBrowser<PropertyUrl>(\n ({ window }) => window.location.href || null,\n () => null\n ),\n referrer: safelyRunOnBrowser<PropertyReferrer>(\n ({ window }) => window.document.referrer || null,\n () => null\n ),\n viewport: getViewport(),\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_ANONYMOUS_ID,\n PREFIX_DEVICE_ID,\n PREFIX_SESSION_ID,\n SESSION_EXPIRATION_TIME_MS,\n TrackingConsent,\n TrackingConsentType,\n} from '../constants';\nimport type {\n AnonymousId,\n DeviceId,\n DistinctId,\n SessionId,\n UserId,\n} from '../types';\nimport { generateId } from './generateId';\nimport { Logger } from './logger';\nimport { type StorageApi } from './storage';\n\ntype SessionData = {\n deviceId: DeviceId;\n distinctId: DistinctId;\n anonymousId: AnonymousId | null;\n sessionId: SessionId;\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 deviceId: parsedData.deviceId || this._generateDeviceId(),\n distinctId: parsedData.distinctId || this._generateAnonymousId(),\n sessionId: parsedData.sessionId || this._generateSessionId(),\n anonymousId: parsedData.anonymousId || 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 getSessionId(): SessionId {\n return this._sessionData.sessionId;\n }\n\n getDeviceId(): DeviceId {\n return this._sessionData.deviceId;\n }\n\n getDistinctId(): DistinctId {\n return this._sessionData.distinctId;\n }\n\n getAnonymousId(): AnonymousId | null {\n return this._sessionData.anonymousId;\n }\n\n /**\n * Returns whether the current user is identified.\n *\n * The `anonymousId` field is a \"before\" snapshot: if set, the user was previously\n * anonymous and is now identified. If `null`, the user is still anonymous.\n *\n * When transitioning from anonymous to identified, we preserve the anonymous ID\n * to enable identity merging on the backend. This allows:\n * - Linking pre-identification events (anonymous ID) to post-identification events (user ID)\n * - Merging user profiles so anonymous browsing behavior is associated with the identified user\n * - Maintaining a complete user journey from first visit through identification\n *\n * **State Transitions:**\n * - **Anonymous:** `anonymousId = null`, `distinctId = anonymousId`, `isIdentified() = false`\n * - **Identified:** `anonymousId = previous distinctId`, `distinctId = userId`, `isIdentified() = true`\n */\n isIdentified(): boolean {\n return Boolean(this._sessionData.anonymousId);\n }\n\n getLastEventAt(): string | null {\n return this._sessionData.lastEventAt;\n }\n\n getTrackingConsent(): TrackingConsentType {\n return this._sessionData.trackingConsent;\n }\n\n identify(userId: UserId): void {\n this._sessionData.anonymousId = this._sessionData.distinctId as AnonymousId;\n this._sessionData.distinctId = 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 resetDeviceId = false,\n resetTrackingConsent = false,\n }: {\n resetDeviceId?: boolean;\n resetTrackingConsent?: boolean;\n } = {}): void {\n if (resetDeviceId) {\n this._sessionData.deviceId = this._generateDeviceId();\n }\n\n if (resetTrackingConsent) {\n this._sessionData.trackingConsent = this._defaultTrackingConsent;\n }\n\n this._sessionData.sessionId = this._generateSessionId();\n this._sessionData.anonymousId = null;\n this._sessionData.distinctId = this._generateAnonymousId();\n this._sessionData.lastEventAt = null;\n this._persistToStorage();\n }\n\n private _createDefaultSessionData(): SessionData {\n return {\n anonymousId: null,\n deviceId: this._generateDeviceId(),\n distinctId: this._generateAnonymousId(),\n lastEventAt: null,\n sessionId: this._generateSessionId(),\n trackingConsent: this._defaultTrackingConsent,\n };\n }\n\n private _generateSessionId(): SessionId {\n return generateId(PREFIX_SESSION_ID);\n }\n\n private _generateDeviceId(): DeviceId {\n return generateId(PREFIX_DEVICE_ID);\n }\n\n private _generateAnonymousId(): AnonymousId {\n return generateId(PREFIX_ANONYMOUS_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 EVENT_PAGEVIEW,\n keyBuilder,\n MAX_QUEUE_SIZE,\n PROPERTY_LIB,\n PROPERTY_LIB_VERSION,\n PROPERTY_REFERER,\n PROPERTY_RELEASE,\n PROPERTY_URL,\n PROPERTY_VIEWPORT,\n REQUEST_TIMEOUT_MS,\n TrackingConsent,\n TrackingConsentType,\n} from './constants';\nimport { isAltertableError, isApiError, isNetworkError } from './lib/error';\nimport { invariant } from './lib/invariant';\nimport { dashboardUrl } from './lib/link';\nimport { createLogger } from './lib/logger';\nimport { parseUrl } from './lib/parseUrl';\nimport { Queue } from './lib/queue';\nimport { Requester } from './lib/requester';\nimport { captureRuntimeContext, RuntimeContext } from './lib/runtimeContext';\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 { getViewport } from './lib/viewport';\nimport {\n AliasPayload,\n AltertableContext,\n DistinctId,\n Environment,\n EventPayload,\n EventProperties,\n EventType,\n IdentifyPayload,\n TrackPayload,\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?: Environment;\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 \"granted\"\n */\n trackingConsent?: TrackingConsentType;\n /**\n * Optional error handler for intercepting SDK errors.\n */\n onError?: (error: Error) => void;\n}\n\nconst DEFAULT_CONFIG: AltertableConfig = {\n autoCapture: true,\n baseUrl: 'https://api.altertable.ai',\n debug: false,\n environment: 'production',\n persistence: 'localStorage+cookie',\n release: undefined,\n trackingConsent: TrackingConsent.GRANTED,\n};\n\nexport class Altertable {\n private _cleanupAutoCapture: (() => void) | undefined;\n private _config: AltertableConfig;\n private _queue: Queue<QueueItem>;\n private _isInitialized = false;\n private _lastUrl: string | null;\n private _logger = createLogger('Altertable');\n private _referrer: string | null;\n private _requester: Requester<EventPayload> | undefined;\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._queue = new Queue<QueueItem>({\n capacity: MAX_QUEUE_SIZE,\n onDropOldest: droppedItem => {\n const method =\n droppedItem.type === 'command'\n ? droppedItem.method\n : droppedItem.eventType;\n this._logger.warnDev(\n `Queue is full (${MAX_QUEUE_SIZE} items). Dropping ${method} call.`\n );\n },\n });\n }\n\n /**\n * Initializes the Altertable SDK with your API key and optional configuration.\n *\n * @param apiKey Your Altertable API key\n * @param config Configuration options\n * @returns A cleanup function to remove event listeners\n *\n * @example\n * ```javascript\n * altertable.init('YOUR_API_KEY', {\n * environment: 'development',\n * });\n * ```\n */\n init(apiKey: string, config: AltertableConfig = {}) {\n invariant(apiKey, 'Missing API key');\n this._config = { ...DEFAULT_CONFIG, ...config };\n this._storageKey = keyBuilder(apiKey, this._config.environment);\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 this._storage = selectStorage(this._config.persistence, {\n onFallback: message => this._logger.warn(message),\n });\n this._requester = new Requester({\n baseUrl: this._config.baseUrl,\n apiKey,\n requestTimeout: REQUEST_TIMEOUT_MS,\n });\n this._sessionManager = new SessionManager({\n storage: this._storage,\n storageKey: this._storageKey,\n logger: this._logger,\n defaultTrackingConsent: this._config.trackingConsent,\n });\n this._sessionManager.init();\n\n this._isInitialized = true;\n\n if (this._config.debug) {\n this._logger.logHeader();\n }\n\n const trackingConsent = this._sessionManager.getTrackingConsent();\n if (trackingConsent === TrackingConsent.GRANTED) {\n this._flushQueue();\n } else if (trackingConsent === TrackingConsent.DENIED) {\n this._queue.clear();\n }\n\n this._handleAutoCaptureChange(this._config.autoCapture);\n\n return () => {\n this._cleanupAutoCapture?.();\n };\n }\n\n /**\n * Updates the configuration after initialization.\n *\n * @param updates Configuration updates to apply\n *\n * @example\n * ```javascript\n * altertable.configure({\n * trackingConsent: 'granted',\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 this._flushQueue();\n } else if (updates.trackingConsent === TrackingConsent.DENIED) {\n this._queue.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 /**\n * Identifies a user with their ID and optional traits.\n *\n * Notes:\n * - You can call this method multiple times with the same ID.\n * - To change traits, use {@link updateTraits} instead.\n * - To switch to a new user ID, call {@link reset} first.\n *\n * @param userId The user's unique identifier\n * @param traits User properties\n *\n * @example\n * ```javascript\n * altertable.identify('u_01jza857w4f23s1hf2s61befmw', {\n * email: 'john.doe@example.com',\n * name: 'John Doe',\n * company: 'Acme Corp',\n * role: 'Software Engineer',\n * });\n * ```\n */\n identify(userId: DistinctId, traits: UserTraits = {}) {\n try {\n validateUserId(userId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'identify',\n args: [userId, { ...traits }],\n });\n return;\n }\n\n this._identify(userId, { ...traits });\n }\n\n private _identify(userId: DistinctId, traits: UserTraits = {}) {\n if (\n this._sessionManager.isIdentified() &&\n userId !== this._sessionManager.getDistinctId()\n ) {\n this._logger.warnDev(\n `User \"${userId}\" is already identified as \"${this._sessionManager.getDistinctId()}\".\\n\\n` +\n `The session has been automatically reset. Use alias() to link the new ID to the existing one if intentional.`\n );\n this.reset();\n }\n\n if (userId !== this._sessionManager.getDistinctId()) {\n this._sessionManager.identify(userId);\n }\n\n const context = this._getContext();\n const payload: IdentifyPayload = {\n environment: context.environment,\n device_id: context.device_id,\n distinct_id: context.distinct_id,\n traits,\n anonymous_id: context.anonymous_id,\n };\n this._processEvent('identify', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logIdentify(payload, { trackingConsent });\n }\n }\n\n /**\n * Link a new ID to the current identity.\n *\n * @param newUserId The new user ID\n *\n * @example\n * ```javascript\n * altertable.alias('u_01jza857w4f23s1hf2s61befmw');\n * ```\n */\n alias(newUserId: DistinctId) {\n try {\n validateUserId(newUserId);\n } catch (error) {\n throw new Error(`[Altertable] ${error.message}`);\n }\n\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'alias',\n args: [newUserId],\n });\n return;\n }\n\n this._alias(newUserId);\n }\n\n private _alias(newUserId: DistinctId) {\n const context = this._getContext();\n\n const payload: AliasPayload = {\n environment: context.environment,\n device_id: context.device_id,\n anonymous_id: context.anonymous_id,\n distinct_id: context.distinct_id,\n new_user_id: newUserId,\n };\n\n this._processEvent('alias', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logAlias(payload, { trackingConsent });\n }\n }\n\n /**\n * Updates user traits for the current user.\n *\n * @param traits User properties to update\n *\n * @example\n * ```javascript\n * altertable.updateTraits({\n * onboarding_completed: true,\n * });\n * ```\n */\n updateTraits(traits: UserTraits) {\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'updateTraits',\n args: [{ ...traits }],\n });\n return;\n }\n\n this._updateTraits({ ...traits });\n }\n\n private _updateTraits(traits: UserTraits) {\n const context = this._getContext();\n\n if (context.anonymous_id === null) {\n this._logger.warnDev(\n 'User must be identified with identify() before updating traits.'\n );\n return;\n }\n\n const payload = {\n environment: context.environment,\n device_id: context.device_id,\n distinct_id: context.distinct_id,\n traits,\n anonymous_id: context.anonymous_id,\n session_id: context.session_id,\n };\n this._processEvent('identify', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logIdentify(payload, { trackingConsent });\n }\n }\n\n /**\n * Resets device and session IDs.\n *\n * @example\n * ```javascript\n * // Reset session, user and visitor (default)\n * altertable.reset();\n *\n * // Reset session, user, visitor and device\n * altertable.reset({\n * resetDeviceId: true,\n * });\n * ```\n */\n reset({\n resetDeviceId = false,\n }: {\n /** Whether to reset device ID (default: false) */\n resetDeviceId?: boolean;\n } = {}) {\n // Clear queued commands to prevent cross-identity/session mixing\n this._queue.clear();\n\n if (!this._isInitialized) {\n return;\n }\n\n this._sessionManager.reset({\n resetDeviceId,\n });\n }\n\n /**\n * Tracks a page view event.\n *\n * When `autoCapture` is enabled (default), this method is automatically called when the page URL changes.\n *\n * @param url The page URL\n *\n * @example\n * ```javascript\n * altertable.page('https://example.com/products');\n * ```\n *\n * @remarks\n * **Page Tracking**: By default, Altertable automatically captures page views. Only use `page()` when you've disabled auto-capture.\n *\n * **Why use auto-capture (default)?**\n * - No manual tracking required\n * - Handles browser navigation events (popstate, hashchange)\n * - Consistent tracking across all page changes\n *\n * **When to use `page()`:**\n * - Custom routing that doesn't trigger browser events\n * - Virtual page views that don't trigger URL changes (modals, step changes)\n * - Server-side tracking where auto-capture isn't available\n */\n page(url: string) {\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'page',\n runtimeContext: captureRuntimeContext(),\n args: [url],\n });\n return;\n }\n\n this._page(url);\n }\n\n private _page(url: string, runtimeContext?: RuntimeContext) {\n const parsedUrl = parseUrl(url);\n const baseUrl = parsedUrl ? parsedUrl.baseUrl : url;\n\n const viewport = runtimeContext?.viewport ?? getViewport();\n const referrer = runtimeContext?.referrer ?? this._referrer;\n\n this._track(\n EVENT_PAGEVIEW,\n {\n [PROPERTY_URL]: baseUrl,\n [PROPERTY_VIEWPORT]: viewport,\n [PROPERTY_REFERER]: referrer,\n ...parsedUrl?.searchParams,\n },\n runtimeContext\n );\n }\n\n /**\n * Tracks a custom event with optional properties.\n *\n * @param eventThe event name\n * @param properties Custom event properties\n *\n * @example\n * ```javascript\n * altertable.track('Purchase Completed', {\n * product_id: 'p_01jza8fr5efvgbxxdd1bwkd0m5',\n * amount: 29.99,\n * currency: 'USD',\n * });\n * ```\n */\n track(event: string, properties: EventProperties = {}) {\n if (!this._isInitialized) {\n this._queue.enqueue({\n type: 'command',\n method: 'track',\n runtimeContext: captureRuntimeContext(),\n args: [event, { ...properties }],\n });\n return;\n }\n\n this._track(event, { ...properties });\n }\n\n private _track(\n event: string,\n properties: EventProperties,\n runtimeContext: RuntimeContext = captureRuntimeContext()\n ) {\n this._sessionManager.renewSessionIfNeeded();\n this._sessionManager.updateLastEventAt(runtimeContext.timestamp);\n\n const context = this._getContext();\n\n // Strip undefined $url to prevent it from overriding computed URL\n const { [PROPERTY_URL]: userUrl, ...restProperties } = properties;\n const hasUrl = userUrl !== undefined;\n const urlForEvent = hasUrl ? null : runtimeContext.url;\n\n const parsedUrl = urlForEvent ? parseUrl(urlForEvent) : null;\n const baseUrl = parsedUrl ? parsedUrl.baseUrl : urlForEvent;\n\n const payload: TrackPayload = {\n timestamp: runtimeContext.timestamp,\n event,\n environment: context.environment,\n device_id: context.device_id,\n distinct_id: context.distinct_id,\n anonymous_id: context.anonymous_id,\n session_id: context.session_id,\n properties: {\n [PROPERTY_LIB]: __LIB__,\n [PROPERTY_LIB_VERSION]: __LIB_VERSION__,\n [PROPERTY_RELEASE]: this._config.release,\n [PROPERTY_URL]: hasUrl ? userUrl : baseUrl,\n // The above properties might be overridden by user-provided fields\n // and the React library\n ...restProperties,\n },\n };\n\n this._processEvent('track', payload);\n\n if (this._config.debug) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n this._logger.logEvent(payload, { trackingConsent });\n }\n }\n\n /**\n * Returns the current tracking consent state.\n *\n * @returns The current tracking consent state\n * @see {@link TrackingConsent}\n *\n * @example\n * ```javascript\n * const consent = altertable.getTrackingConsent();\n * if (consent === 'granted') {\n * // Tracking is allowed\n * }\n * ```\n */\n getTrackingConsent(): TrackingConsentType {\n if (!this._isInitialized) {\n return TrackingConsent.PENDING;\n }\n return this._sessionManager.getTrackingConsent();\n }\n\n private _flushQueue() {\n const items = this._queue.flush();\n\n if (items.length === 0) {\n return;\n }\n\n if (this._config.debug) {\n this._logger.log(\n `Processing ${items.length} queued ${items.length === 1 ? 'item' : 'items'}.`\n );\n }\n\n for (const item of items) {\n this._executeQueueItem(item);\n }\n }\n\n private _executeQueueItem(item: QueueItem) {\n if (item.type === 'event') {\n // Send pre-built payload directly (preserves original session context)\n this._sendEvent(item.eventType, item.payload);\n return;\n }\n // Execute command (pre-init path)\n this._executeCommand(item);\n }\n\n private _executeCommand(cmd: QueuedCommand) {\n try {\n switch (cmd.method) {\n case 'identify':\n this._identify(...cmd.args);\n break;\n case 'track':\n this._track(...cmd.args, cmd.runtimeContext);\n break;\n case 'page':\n this._page(...cmd.args, cmd.runtimeContext);\n break;\n case 'alias':\n this._alias(...cmd.args);\n break;\n case 'updateTraits':\n this._updateTraits(...cmd.args);\n break;\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n this._logger.warnDev(\n `Failed to process queued ${cmd.method}() command:\\n${errorMessage}`\n );\n }\n }\n\n private _checkForChanges() {\n safelyRunOnBrowser(({ window }) => {\n const currentUrl = window.location.href;\n if (currentUrl !== this._lastUrl) {\n this._referrer = this._lastUrl;\n this._lastUrl = currentUrl;\n this.page(currentUrl);\n }\n });\n }\n\n private _getContext(): AltertableContext {\n return {\n environment: this._config.environment,\n device_id: this._sessionManager.getDeviceId(),\n distinct_id: this._sessionManager.getDistinctId(),\n anonymous_id: this._sessionManager.getAnonymousId(),\n session_id: this._sessionManager.getSessionId(),\n };\n }\n\n private _processEvent<TPayload extends EventPayload>(\n eventType: EventType,\n payload: TPayload\n ) {\n const trackingConsent = this._sessionManager.getTrackingConsent();\n\n switch (trackingConsent) {\n case TrackingConsent.GRANTED:\n this._sendEvent(eventType, payload);\n break;\n case TrackingConsent.PENDING:\n case TrackingConsent.DISMISSED:\n this._queue.enqueue({\n type: 'event',\n eventType,\n payload,\n });\n break;\n case TrackingConsent.DENIED:\n // Do nothing (don't collect or send data)\n break;\n }\n }\n\n private async _sendEvent<TPayload extends EventPayload>(\n eventType: EventType,\n payload: TPayload\n ) {\n try {\n await this._requester.send(`/${eventType}`, payload);\n } catch (error) {\n if (isAltertableError(error)) {\n this._config.onError?.(error);\n }\n\n if (isApiError(error) && error.errorCode === 'environment-not-found') {\n this._logger.warnDev(\n `Environment \"${this._config.environment}\" not found. Please create this environment in your Altertable dashboard at ${dashboardUrl(`/environments/new?name=${this._config.environment}`)} before tracking events.`\n );\n } else if (isNetworkError(error)) {\n this._logger.error('Network error while sending event', {\n error: error.message,\n cause: error.cause,\n eventType,\n });\n } else {\n this._logger.error('Failed to send event', {\n error,\n eventType,\n payload,\n });\n }\n }\n }\n}\n\ntype QueuedCommand =\n | {\n type: 'command';\n method: 'identify';\n args: Parameters<Altertable['identify']>;\n }\n | {\n type: 'command';\n method: 'track';\n args: Parameters<Altertable['track']>;\n runtimeContext: RuntimeContext;\n }\n | {\n type: 'command';\n method: 'page';\n args: Parameters<Altertable['page']>;\n runtimeContext: RuntimeContext;\n }\n | {\n type: 'command';\n method: 'alias';\n args: Parameters<Altertable['alias']>;\n }\n | {\n type: 'command';\n method: 'updateTraits';\n args: Parameters<Altertable['updateTraits']>;\n };\n\ntype QueuedEvent = {\n type: 'event';\n eventType: EventType;\n payload: EventPayload;\n};\n\ntype QueueItem = QueuedCommand | QueuedEvent;\n"],"mappings":"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","names":["index_exports","__export","TrackingConsent","altertable","createKeyBuilder","prefix","separator","parts","STORAGE_KEY_PREFIX","keyBuilder","createKeyBuilder","STORAGE_KEY_TEST","PREFIX_SESSION_ID","PREFIX_ANONYMOUS_ID","PREFIX_DEVICE_ID","MINUTE_IN_MS","AUTO_CAPTURE_INTERVAL_MS","SESSION_EXPIRATION_TIME_MS","MAX_QUEUE_SIZE","REQUEST_TIMEOUT_MS","EVENT_PAGEVIEW","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_REFERER","PROPERTY_RELEASE","PROPERTY_URL","PROPERTY_VIEWPORT","TrackingConsent","RESERVED_USER_IDS","RESERVED_USER_IDS_CASE_SENSITIVE","AltertableError","message","ApiError","status","statusText","errorCode","details","requestContext","NetworkError","cause","isAltertableError","error","isApiError","isNetworkError","invariant","condition","message","InvariantError","_InvariantError","dashboardUrl","path","createLogger","prefix","args","header","loggerCache","payload","trackingConsent","eventBadgeLabel","eventBadgeStyle","createEventBadgeElement","eventTitleLabel","eventTitleStyle","createEventTitleElement","PROPERTY_URL","environmentBadgeLabel","environmentBadgeStyle","createEnvironmentBadgeElement","timestampLabel","timestampStyle","createTimestampElement","consentBadgeLabel","consentBadgeStyle","getConsentBadgeElement","userLabel","userLabelStyle","createEventLabelElement","userValueLabel","userValueStyle","createValueElement","anonymousLabel","anonymousLabelStyle","anonymousValueLabel","anonymousValueStyle","sessionLabel","sessionLabelStyle","sessionValueLabel","sessionValueStyle","distinctIdLabel","distinctIdLabelStyle","distinctIdValueLabel","distinctIdValueStyle","anonymousalueLabel","newUserIdLabel","newUserIdLabelStyle","newUserIdValueLabel","newUserIdValueStyle","message","hasAlreadyPrinted","sanitizedMessage","warning","formatEventTime","timestamp","getEventBadgeColor","event","value","getEnvironmentColor","environment","TrackingConsent","parseUrl","url","parsedUrl","Queue","options","command","dropped","items","isBeaconSupported","Requester","config","path","payload","isBeaconSupported","url","data","controller","timeoutId","response","errorResponse","ApiError","error","NetworkError","safelyRunOnBrowser","callback","fallback","getViewport","safelyRunOnBrowser","window","captureRuntimeContext","safelyRunOnBrowser","window","getViewport","generateId","prefix","SessionManager","options","TrackingConsent","storedData","parsedData","isValidTrackingConsent","userId","consent","timestamp","resetDeviceId","resetTrackingConsent","generateId","PREFIX_SESSION_ID","PREFIX_DEVICE_ID","PREFIX_ANONYMOUS_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","DEFAULT_CONFIG","TrackingConsent","Altertable","createLogger","Queue","MAX_QUEUE_SIZE","droppedItem","method","apiKey","config","invariant","keyBuilder","safelyRunOnBrowser","window","selectStorage","message","Requester","REQUEST_TIMEOUT_MS","SessionManager","trackingConsent","updates","previousStorage","currentTrackingConsent","enableAutoCapture","checkForChanges","intervalId","AUTO_CAPTURE_INTERVAL_MS","userId","traits","validateUserId","error","context","payload","newUserId","resetDeviceId","url","captureRuntimeContext","runtimeContext","parsedUrl","parseUrl","baseUrl","viewport","getViewport","referrer","EVENT_PAGEVIEW","PROPERTY_URL","PROPERTY_VIEWPORT","PROPERTY_REFERER","event","properties","userUrl","restProperties","hasUrl","urlForEvent","PROPERTY_LIB","PROPERTY_LIB_VERSION","PROPERTY_RELEASE","items","item","cmd","errorMessage","currentUrl","eventType","isAltertableError","isApiError","dashboardUrl","isNetworkError","altertable","Altertable","safelyRunOnBrowser","window","stub","item","method","args"]}