@traffical/js-client 0.6.0 → 0.7.0

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,3 +1,3 @@
1
- /* @traffical/js-client v0.6.0 */
2
- "use strict";var Traffical=(()=>{var N=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var ke=(r,e,t)=>e in r?N(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var Ce=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Pe=(r,e)=>{for(var t in e)N(r,t,{get:e[t],enumerable:!0})},Se=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ee(e))!Te.call(r,i)&&i!==t&&N(r,i,{get:()=>e[i],enumerable:!(n=Ie(e,i))||n.enumerable});return r};var we=r=>Se(N({},"__esModule",{value:!0}),r);var x=(r,e,t)=>(ke(r,typeof e!="symbol"?e+"":e,t),t);var fe=Ce(()=>{});var Ct={};Pe(Ct,{TrafficalClient:()=>C,createDOMBindingPlugin:()=>xe,createRedirectAttributionPlugin:()=>le,createRedirectPlugin:()=>ae,destroy:()=>kt,init:()=>It,initSync:()=>Et,instance:()=>Tt});function T(r){let e=2166136261;for(let t=0;t<r.length;t++)e^=r.charCodeAt(t),e=Math.imul(e,16777619);return e>>>0}function B(r,e,t){let n=`${r}:${e}`;return T(n)%t}function G(r,e){return r>=e[0]&&r<=e[1]}function L(r,e){for(let t of e)if(G(r,t.bucketRange))return t;return null}function k(r,e){if(r.length===0||r.length===1)return 0;let n=T(e)%1e4/1e4,i=0;for(let o=0;o<r.length;o++)if(i+=r[o],n<i)return o;return r.length-1}function J(r,e){let{field:t,op:n,value:i,values:o}=r,s=Me(e,t);switch(n){case"eq":return s===i;case"neq":return s!==i;case"in":return Array.isArray(o)?o.includes(s):!1;case"nin":return Array.isArray(o)?!o.includes(s):!0;case"gt":return typeof s=="number"&&s>i;case"gte":return typeof s=="number"&&s>=i;case"lt":return typeof s=="number"&&s<i;case"lte":return typeof s=="number"&&s<=i;case"contains":return typeof s=="string"&&typeof i=="string"&&s.includes(i);case"startsWith":return typeof s=="string"&&typeof i=="string"&&s.startsWith(i);case"endsWith":return typeof s=="string"&&typeof i=="string"&&s.endsWith(i);case"regex":if(typeof s!="string"||typeof i!="string")return!1;try{return new RegExp(i).test(s)}catch{return!1}case"exists":return s!=null;case"notExists":return s==null;default:return!1}}function K(r,e){return r.length===0?!0:r.every(t=>J(t,e))}function Me(r,e){let t=e.split("."),n=r;for(let i of t){if(n==null)return;if(typeof n=="object")n=n[i];else return}return n}function Y(r,e){let t=r.intercept;for(let{key:n,coef:i,missing:o}of r.numeric){let s=e[n];t+=typeof s=="number"?i*s:o}for(let{key:n,values:i,missing:o}of r.categorical){let s=e[n],a=s!=null?String(s):null;t+=a!==null&&a in i?i[a]:o}return t}function Z(r,e){if(r.length===0)return[];if(r.length===1)return[1];let t=Math.max(e,1e-10),n=r.map(a=>a/t),i=Math.max(...n),o=n.map(a=>Math.exp(a-i)),s=o.reduce((a,l)=>a+l,0);return o.map(a=>a/s)}function Q(r,e){if(r.length===0)return[];if(e<=0)return r;let t=r.length,n=1/t,i=Math.min(e,n),o=r.map(a=>Math.max(a,i)),s=o.reduce((a,l)=>a+l,0);return s===0?Array(t).fill(1/t):o.map(a=>a/s)}function V(r,e,t){let n=r.contextualModel;if(!n||r.allocations.length===0)return null;let i=Re(n,r.allocations,e),o=Z(i,n.gamma),s=Q(o,n.actionProbabilityFloor),a=`ctx:${t}:${r.id}`,l=k(s,a);return r.allocations[l]}function Re(r,e,t){return e.map(n=>{let i=r.coefficients[n.name];return i?Y(i,t):r.defaultAllocationScore})}var Oe=r=>crypto.getRandomValues(new Uint8Array(r)),Ne=(r,e,t)=>{let n=(2<<Math.log2(r.length-1))-1,i=-~(1.6*n*e/r.length);return(o=e)=>{let s="";for(;;){let a=t(i),l=i|0;for(;l--;)if(s+=r[a[l]&n]||"",s.length>=o)return s}}},de=(r,e=21)=>Ne(r,e|0,Oe);function F(r){let e=new Error(r);return e.source="ulid",e}var ee="0123456789ABCDEFGHJKMNPQRSTVWXYZ",P=ee.length,ge=Math.pow(2,48)-1,Be=10,Le=16;function Ke(r){let e=Math.floor(r()*P);return e===P&&(e=P-1),ee.charAt(e)}function Ve(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>ge)throw F("cannot encode time greater than "+ge);if(r<0)throw F("time must be positive");if(Number.isInteger(Number(r))===!1)throw F("time must be an integer");let t,n="";for(;e>0;e--)t=r%P,n=ee.charAt(t)+n,r=(r-t)/P;return n}function Fe(r,e){let t="";for(;r>0;r--)t=Ke(e)+t;return t}function $e(r=!1,e){e||(e=typeof window<"u"?window:null);let t=e&&(e.crypto||e.msCrypto);if(t)return()=>{let n=new Uint8Array(1);return t.getRandomValues(n),n[0]/255};try{let n=fe();return()=>n.randomBytes(1).readUInt8()/255}catch{}if(r){try{console.error("secure crypto unusable, falling back to insecure Math.random()!")}catch{}return()=>Math.random()}throw F("secure crypto unusable, insecure Math.random not allowed")}function je(r){return r||(r=$e()),function(t){return isNaN(t)&&(t=Date.now()),Ve(t,Be)+Fe(Le,r)}}var pe=je();var Ue="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",ze=8,Ht=de(Ue,ze);function $(r){return`${r}_${pe()}`}function S(){return $("dec")}function te(){return $("exp")}function ne(){return $("trk")}function We(r,e){let t=new Set;for(let i of e)if(i.contextLogging?.allowedFields)for(let o of i.contextLogging.allowedFields)t.add(o);if(t.size===0)return;let n={};for(let i of t)i in r&&(n[i]=r[i]);return Object.keys(n).length>0?n:void 0}function He(r,e){let t=[];for(let n of r){let i=e[n];if(i==null)return null;t.push(String(i))}return t.join("_")}function he(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function qe(r,e,t,n){let i=r.entityState?.[e];if(!i)return he(n);let o=i.entities[t];if(o&&o.weights.length===n)return o.weights;let s=i._global;return s&&s.weights.length===n?s.weights:he(n)}function Xe(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=He(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let p=i.dynamicAllocations.countKey,v=t[p];if(typeof v!="number"||v<=0)return null;a=Math.floor(v),s=Array.from({length:a},(c,d)=>({id:`${e.id}_dynamic_${d}`,name:String(d),bucketRange:[0,0],overrides:{}}))}else s=e.allocations,a=s.length;if(a===0)return null;let l=qe(r,e.id,o,a),m=`${o}:${n}:${e.id}`,b=k(l,m);return{allocation:s[b],entityId:o}}function w(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function me(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=w(r,e);if(!a)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let l=new Set(Object.keys(t)),m=r.parameters.filter(p=>l.has(p.key));for(let p of m)p.key in i&&(i[p.key]=p.default);let b=new Map;for(let p of m){let v=b.get(p.layerId)||[];v.push(p),b.set(p.layerId,v)}for(let p of r.layers){let v=b.get(p.id),c=v&&v.length>0,d=B(a,p.id,r.hashing.bucketCount),h,f;for(let u of p.policies)if(u.state==="running"){if(u.eligibleBucketRange){let{start:g,end:y}=u.eligibleBucketRange;if(d<g||d>y)continue}if(K(u.conditions,e)){if(u.contextualModel){let g=V(u,e,a);if(g){if(h=u,f=g,s.push(u),c)for(let[y,I]of Object.entries(g.overrides))y in i&&(i[y]=I);break}}if(u.entityConfig&&u.entityConfig.resolutionMode==="bundle"){let g=Xe(r,u,e,a);if(g){if(h=u,f=g.allocation,s.push(u),c&&!u.entityConfig.dynamicAllocations)for(let[y,I]of Object.entries(g.allocation.overrides))y in i&&(i[y]=I);break}}else if(u.entityConfig&&u.entityConfig.resolutionMode==="edge"){let g=n?.edgeResults?.get(u.id);if(g){if(h=u,s.push(u),u.entityConfig.dynamicAllocations)f={id:`${u.id}_dynamic_${g.allocationIndex}`,name:String(g.allocationIndex),bucketRange:[0,0],overrides:{}};else if(u.allocations[g.allocationIndex]&&(f=u.allocations[g.allocationIndex],c&&f))for(let[y,I]of Object.entries(f.overrides))y in i&&(i[y]=I);break}continue}else{let g=L(d,u.allocations);if(g){if(h=u,f=g,s.push(u),c)for(let[y,I]of Object.entries(g.overrides))y in i&&(i[y]=I);break}}}}o.push({layerId:p.id,bucket:d,policyId:h?.id,policyKey:h?.key,allocationId:f?.id,allocationName:f?.name,allocationKey:f?.key,...c?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function j(r,e,t,n){return me(r,e,t,n).assignments}function U(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=me(r,e,t,n),l=We(e,a);return{decisionId:S(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:l}}}var E=class r{constructor(e={}){x(this,"_seen",new Map);x(this,"_ttlMs");x(this,"_maxEntries");x(this,"_lastCleanup",Date.now());this._ttlMs=e.ttlMs??36e5,this._maxEntries=e.maxEntries??1e4}static hashAssignments(e){let t=Object.keys(e).sort(),n=[];for(let i of t){let o=e[i],s=typeof o=="object"?JSON.stringify(o):String(o);n.push(`${i}=${s}`)}return n.join("|")}static createKey(e,t){return`${e}:${t}`}checkAndMark(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o!==void 0&&i-o<this._ttlMs?!1:(this._seen.set(n,i),this._maybeCleanup(i),!0)}wouldBeNew(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o===void 0?!0:i-o>=this._ttlMs}clear(){this._seen.clear()}get size(){return this._seen.size}_maybeCleanup(e){(e-this._lastCleanup>this._ttlMs*.2||this._seen.size>this._maxEntries)&&(this._lastCleanup=e,this._cleanup(e))}_cleanup(e){let t=[];for(let[n,i]of this._seen.entries())e-i>=this._ttlMs&&t.push(n);for(let n of t)this._seen.delete(n);if(this._seen.size>this._maxEntries){let i=Array.from(this._seen.entries()).sort((o,s)=>o[1]-s[1]).slice(0,this._seen.size-this._maxEntries);for(let[o]of i)this._seen.delete(o)}}};var A=class{constructor(e){x(this,"config");x(this,"defaultTimeout");this.config=e,this.defaultTimeout=e.defaultTimeoutMs??5e3}async resolve(e){try{let t=new AbortController,n=setTimeout(()=>t.abort(),this.defaultTimeout),i=`${this.config.baseUrl}/v1/resolve`,o=await fetch(i,{method:"POST",headers:this._headers(),body:JSON.stringify({context:e.context,env:e.env??this.config.env,parameters:e.parameters}),signal:t.signal});return clearTimeout(n),o.ok?await o.json():(console.warn(`[Traffical] Resolve failed: ${o.status} ${o.statusText}`),null)}catch(t){return t instanceof Error&&t.name==="AbortError"?console.warn(`[Traffical] Resolve timed out after ${this.defaultTimeout}ms`):console.warn("[Traffical] Resolve error:",t),null}}async decideEntity(e,t){let n=t??Math.min(this.defaultTimeout,100);try{let i=new AbortController,o=setTimeout(()=>i.abort(),n),s=`${this.config.baseUrl}/v1/decide/${e.policyId}`,a=await fetch(s,{method:"POST",headers:this._headers(),body:JSON.stringify({entityId:e.entityId,unitKeyValue:e.unitKeyValue,allocationCount:e.allocationCount,context:e.context}),signal:i.signal});return clearTimeout(o),a.ok?await a.json():(console.warn(`[Traffical] Edge decide failed: ${a.status} ${a.statusText}`),null)}catch(i){return i instanceof Error&&i.name==="AbortError"?console.warn(`[Traffical] Edge decide timed out after ${n}ms`):console.warn("[Traffical] Edge decide error:",i),null}}async decideEntityBatch(e,t){if(e.length===0)return[];if(e.length===1)return[await this.decideEntity(e[0],t)];let n=t??Math.min(this.defaultTimeout,200);try{let i=new AbortController,o=setTimeout(()=>i.abort(),n),s=`${this.config.baseUrl}/v1/decide/batch`,a=await fetch(s,{method:"POST",headers:this._headers(),body:JSON.stringify({requests:e}),signal:i.signal});return clearTimeout(o),a.ok?(await a.json()).responses:(console.warn(`[Traffical] Edge batch decide failed: ${a.status} ${a.statusText}`),e.map(()=>null))}catch(i){return i instanceof Error&&i.name==="AbortError"?console.warn(`[Traffical] Edge batch decide timed out after ${n}ms`):console.warn("[Traffical] Edge batch decide error:",i),e.map(()=>null)}}_headers(){return{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`,"X-Org-Id":this.config.orgId,"X-Project-Id":this.config.projectId,"X-Env":this.config.env}}};function ie(r,e,t,n,i){let o=[];for(let a of e){let l=t[a];if(l==null)return null;o.push(String(l))}let s=o.join("_");return{policyId:r,entityId:s,unitKeyValue:n,allocationCount:i,context:t}}var z=class{constructor(e={}){this._seen=new Set;this._lastError=null;this._options=e}capture(e,t,n){try{return t()}catch(i){return this._onError(e,i),n}}async captureAsync(e,t,n){try{return await t()}catch(i){return this._onError(e,i),n}}async swallow(e,t){try{await t()}catch(n){this._onError(e,n)}}getLastError(){let e=this._lastError;return this._lastError=null,e}clearSeen(){this._seen.clear()}_onError(e,t){let n=this._resolveError(t);this._lastError=n;let i=`${e}:${n.name}:${n.message}`;this._seen.has(i)||(this._seen.add(i),console.warn(`[Traffical] Error in ${e}:`,n.message),this._options.onError?.(e,n),this._options.reportErrors&&this._options.errorEndpoint&&this._reportError(e,n).catch(()=>{}))}async _reportError(e,t){if(this._options.errorEndpoint)try{await fetch(this._options.errorEndpoint,{method:"POST",headers:{"Content-Type":"application/json",...this._options.sdkKey&&{"X-Traffical-Key":this._options.sdkKey}},body:JSON.stringify({tag:e,error:t.name,message:t.message,stack:t.stack,timestamp:new Date().toISOString(),sdk:"@traffical/js-client",userAgent:typeof navigator<"u"?navigator.userAgent:void 0})})}catch{}}_resolveError(e){return e instanceof Error?e:typeof e=="string"?new Error(e):new Error("An unknown error occurred")}};var W="failed_events";var H=class{constructor(e){this._queue=[];this._flushTimer=null;this._isFlushing=!1;this._endpoint=e.endpoint,this._apiKey=e.apiKey,this._storage=e.storage,this._batchSize=e.batchSize??10,this._flushIntervalMs=e.flushIntervalMs??3e4,this._onError=e.onError,this._lifecycleProvider=e.lifecycleProvider,this._setupListeners(),this._retryFailedEvents(),this._startFlushTimer()}log(e){this._queue.push(e),this._queue.length>=this._batchSize&&this.flush()}async flush(){if(this._isFlushing||this._queue.length===0)return;this._isFlushing=!0;let e=[...this._queue];this._queue=[];try{await this._sendEvents(e)}catch(t){this._persistFailedEvents(e),this._onError?.(t instanceof Error?t:new Error(String(t)))}finally{this._isFlushing=!1}}flushBeacon(){if(this._queue.length===0)return!0;if(typeof fetch>"u")return this.flush(),!1;let e=[...this._queue];return this._queue=[],fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e}),keepalive:!0}).catch(()=>{this._persistFailedEvents(e)}),!0}get queueSize(){return this._queue.length}destroy(){this._flushTimer&&(clearInterval(this._flushTimer),this._flushTimer=null),this._removeListeners()}async _sendEvents(e){let t=await fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e})});if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`)}_persistFailedEvents(e){let n=[...this._storage.get(W)??[],...e].slice(-100);this._storage.set(W,n)}_retryFailedEvents(){let e=this._storage.get(W);!e||e.length===0||(this._storage.remove(W),this._queue.push(...e))}_startFlushTimer(){this._flushIntervalMs<=0||(this._flushTimer=setInterval(()=>{this.flush().catch(()=>{})},this._flushIntervalMs))}_setupListeners(){this._lifecycleProvider&&(this._visibilityCallback=e=>{e==="background"?this._lifecycleProvider?.isUnloading()?this.flushBeacon():this.flush().catch(()=>{}):this._retryFailedEvents()},this._lifecycleProvider.onVisibilityChange(this._visibilityCallback))}_removeListeners(){this._lifecycleProvider&&this._visibilityCallback&&(this._lifecycleProvider.removeVisibilityListener(this._visibilityCallback),this._visibilityCallback=void 0)}};var D="exposure_dedup";var M=class r{constructor(e){this._storage=e.storage,this._sessionTtlMs=e.sessionTtlMs??18e5,this._seen=new Set,this._sessionStart=Date.now(),this._restore()}static createKey(e,t,n){return`${e}:${t}:${n}`}shouldTrack(e){return this._isSessionExpired()&&this._resetSession(),this._seen.has(e)?!1:(this._seen.add(e),this._persist(),!0)}checkAndMark(e,t,n){let i=r.createKey(e,t,n);return this.shouldTrack(i)}clear(){this._seen.clear(),this._storage.remove(D)}get size(){return this._seen.size}_isSessionExpired(){return Date.now()-this._sessionStart>this._sessionTtlMs}_resetSession(){this._seen.clear(),this._sessionStart=Date.now(),this._storage.remove(D)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(D,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(D);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(D);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var R="stable_id",ct="traffical_sid";var q=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??ct}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(R);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(R,e),this._cachedId=e,e):(e=this._generateId(),this._persist(e),this._cachedId=e,e)}setId(e){this._persist(e),this._cachedId=e}clear(){this._storage.remove(R),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(R)!==null||this._getCookie()!==null}_persist(e){this._storage.set(R,e),this._useCookieFallback&&this._setCookie(e)}_generateId(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}_getCookie(){if(typeof document>"u")return null;try{let e=document.cookie.split(";");for(let t of e){let[n,i]=t.trim().split("=");if(n===this._cookieName&&i)return decodeURIComponent(i)}}catch{}return null}_setCookie(e){if(!(typeof document>"u"))try{document.cookie=`${this._cookieName}=${encodeURIComponent(e)}; max-age=31536000; path=/; SameSite=Lax`}catch{}}_deleteCookie(){if(!(typeof document>"u"))try{document.cookie=`${this._cookieName}=; max-age=0; path=/`}catch{}}};var O="traffical:",re=class{constructor(){this._available=this._checkAvailability()}get(e){if(!this._available)return null;try{let t=localStorage.getItem(O+e);if(!t)return null;let n=JSON.parse(t);return n.expiresAt&&Date.now()>n.expiresAt?(this.remove(e),null):n.value}catch{return null}}set(e,t,n){if(this._available)try{let i={value:t,...n&&{expiresAt:Date.now()+n}};localStorage.setItem(O+e,JSON.stringify(i))}catch{}}remove(e){if(this._available)try{localStorage.removeItem(O+e)}catch{}}clear(){if(this._available)try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n?.startsWith(O)&&e.push(n)}e.forEach(t=>localStorage.removeItem(t))}catch{}}_checkAvailability(){try{let e=O+"__test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}},oe=class{constructor(){this._store=new Map}get(e){let t=this._store.get(e);return t?t.expiresAt&&Date.now()>t.expiresAt?(this.remove(e),null):t.value:null}set(e,t,n){this._store.set(e,{value:t,...n&&{expiresAt:Date.now()+n}})}remove(e){this._store.delete(e)}clear(){this._store.clear()}};function ye(){let r=new re;return r.get("__check__")!==null||ut()?r:new oe}function ut(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var dt="js-client",ft="0.1.0";function se(r,e){let t=new E({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=E.hashAssignments(n.assignments);if(!t.checkAndMark(i,o))return;let s={type:"decision",id:n.decisionId,orgId:e.orgId,projectId:e.projectId,env:e.env,unitKey:i,timestamp:n.metadata.timestamp,assignments:n.assignments,layers:n.metadata.layers,context:n.metadata.filteredContext,sdkName:dt,sdkVersion:ft};e.log(s)},onDestroy(){t.clear()}}}var gt="traffical_rdr";function pt(r,e,t){if(!(typeof document>"u"))try{document.cookie=`${r}=${encodeURIComponent(e)}; max-age=${t}; path=/; SameSite=Lax`}catch{}}function ae(r={}){let e=r.parameterKey??"redirect.url",t=r.compareMode??"pathname",n=r.cookieName??gt;return{name:"redirect",onInitialize(i){typeof window>"u"||i.decide({context:{},defaults:{[e]:""}})},onBeforeDecision(i){return typeof window>"u"?i:{"url.pathname":window.location.pathname,...i}},onDecision(i){let o=i.assignments[e];if(typeof o!="string"||!o)return;let s=t==="href"?window.location.href:window.location.pathname;if(o===s)return;let a=i.metadata.layers.find(l=>l.policyId&&l.allocationName);a&&pt(n,JSON.stringify({l:a.layerId,p:a.policyId,a:a.allocationName,ts:Date.now()}),86400),window.location.replace(o)}}}var ht="traffical_rdr";function mt(r){if(typeof document>"u")return null;try{for(let e of document.cookie.split(";")){let[t,n]=e.trim().split("=");if(t===r&&n)return decodeURIComponent(n)}}catch{}return null}function yt(r,e){let t=mt(r);if(!t)return null;try{let n=JSON.parse(t);return Date.now()-n.ts>e?null:{layerId:n.l,policyId:n.p,allocationName:n.a}}catch{return null}}function le(r={}){let e=r.cookieName??ht,t=r.expiryMs??864e5;function n(i){let o=yt(e,t);if(!o)return;i.attribution=i.attribution??[],i.attribution.some(a=>a.layerId===o.layerId&&a.policyId===o.policyId)||i.attribution.push(o)}return{name:"redirect-attribution",onTrack(i){return n(i),!0},onExposure(i){return n(i),!0}}}var X=class{constructor(){this._plugins=[]}register(e){let t="plugin"in e?e.plugin:e,n="priority"in e?e.priority??0:0;if(this._plugins.some(i=>i.plugin.name===t.name)){console.warn(`[Traffical] Plugin "${t.name}" already registered, skipping.`);return}this._plugins.push({plugin:t,priority:n}),this._plugins.sort((i,o)=>o.priority-i.priority)}unregister(e){let t=this._plugins.findIndex(n=>n.plugin.name===e);return t===-1?!1:(this._plugins.splice(t,1),!0)}get(e){return this._plugins.find(t=>t.plugin.name===e)?.plugin}getAll(){return this._plugins.map(e=>e.plugin)}async runInitialize(e){for(let{plugin:t}of this._plugins)if(t.onInitialize)try{await t.onInitialize(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onInitialize error:`,n)}}runConfigUpdate(e){for(let{plugin:t}of this._plugins)if(t.onConfigUpdate)try{t.onConfigUpdate(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onConfigUpdate error:`,n)}}runBeforeDecision(e){let t=e;for(let{plugin:n}of this._plugins)if(n.onBeforeDecision)try{let i=n.onBeforeDecision(t);i&&(t=i)}catch(i){console.warn(`[Traffical] Plugin "${n.name}" onBeforeDecision error:`,i)}return t}runDecision(e){for(let{plugin:t}of this._plugins)if(t.onDecision)try{t.onDecision(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onDecision error:`,n)}}runResolve(e){for(let{plugin:t}of this._plugins)if(t.onResolve)try{t.onResolve(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onResolve error:`,n)}}runExposure(e){for(let{plugin:t}of this._plugins)if(t.onExposure)try{if(t.onExposure(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onExposure error:`,n)}return!0}runTrack(e){for(let{plugin:t}of this._plugins)if(t.onTrack)try{if(t.onTrack(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onTrack error:`,n)}return!0}runDestroy(){for(let{plugin:e}of this._plugins)if(e.onDestroy)try{e.onDestroy()}catch(t){console.warn(`[Traffical] Plugin "${e.name}" onDestroy error:`,t)}}clear(){this._plugins=[]}};function _e(){let r=[],e=!1;function t(s){for(let a of r)a(s)}let n=()=>{e=!0,t("background")},i=()=>{typeof document<"u"&&t(document.visibilityState==="hidden"?"background":"foreground")},o=()=>{e=!0,t("background")};return typeof window<"u"&&(window.addEventListener("pagehide",n),window.addEventListener("beforeunload",o)),typeof document<"u"&&document.addEventListener("visibilitychange",i),{onVisibilityChange(s){r.push(s)},removeVisibilityListener(s){let a=r.indexOf(s);a!==-1&&r.splice(a,1)},isUnloading(){return e}}}var ce="js-client",ue="0.1.0",_t="https://sdk.traffical.io",vt=6e4,bt=3e5,xt=100,C=class{constructor(e){this._state={bundle:null,etag:null,lastFetchTime:0,lastOfflineWarning:0,refreshTimer:null,isInitialized:!1,serverResponse:null,cachedEdgeResults:null};this._decisionCache=new Map;this._cumulativeAttribution=new Map;let t=e.evaluationMode??"bundle";this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??_t,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??vt,attributionMode:e.attributionMode??"cumulative",evaluationMode:t};let n={baseUrl:this._options.baseUrl,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,apiKey:this._options.apiKey};if(this._decisionClient=new A(n),this._errorBoundary=new z(e.errorBoundary),this._storage=e.storage??ye(),this._lifecycleProvider=e.lifecycleProvider??_e(),this._eventLogger=new H({endpoint:`${this._options.baseUrl}/v1/events/batch`,apiKey:e.apiKey,storage:this._storage,lifecycleProvider:this._lifecycleProvider,batchSize:e.eventBatchSize,flushIntervalMs:e.eventFlushIntervalMs,onError:i=>{console.warn("[Traffical] Event logging error:",i.message)}}),this._exposureDedup=new M({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new q({storage:this._storage}),this._plugins=new X,this._assignmentLogger=e.assignmentLogger,this._disableCloudEvents=e.disableCloudEvents??!1,this._assignmentLoggerDedup=e.deduplicateAssignmentLogger!==!1&&e.assignmentLogger?new M({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}):null,e.trackDecisions!==!1&&!this._disableCloudEvents&&this._plugins.register({plugin:se({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:i=>this._eventLogger.log(i)}),priority:100}),e.plugins)for(let i of e.plugins)this._plugins.register(i);this._options.localConfig&&(this._state.bundle=this._options.localConfig,this._plugins.runConfigUpdate(this._options.localConfig))}async initialize(){await this._errorBoundary.captureAsync("initialize",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig(),this._startBackgroundRefresh(),this._state.isInitialized=!0,await this._plugins.runInitialize(this)},void 0)}get isInitialized(){return this._state.isInitialized}destroy(){this._state.refreshTimer&&(clearInterval(this._state.refreshTimer),this._state.refreshTimer=null),this._lifecycleProvider.isUnloading()?this._eventLogger.flushBeacon():this._eventLogger.flush().catch(()=>{}),this._eventLogger.destroy(),this._plugins.runDestroy()}async refreshConfig(){await this._errorBoundary.swallow("refreshConfig",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig()})}getConfigVersion(){return this._state.serverResponse?.stateVersion??this._state.bundle?.version??null}getParams(e){return this._errorBoundary.capture("getParams",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let o={...e.defaults};for(let[s,a]of Object.entries(this._state.serverResponse.assignments))s in o&&(o[s]=a);return this._plugins.runResolve(o),o}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context),i=j(t,n,e.defaults);return this._plugins.runResolve(i),i},e.defaults)}decide(e){return this._errorBoundary.capture("decide",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let s=this._state.serverResponse,a={...e.defaults};for(let[m,b]of Object.entries(s.assignments))m in a&&(a[m]=b);let l={decisionId:s.decisionId,assignments:a,metadata:s.metadata};return this._cacheDecision(l),this._updateCumulativeAttribution(l),this._plugins.runDecision(l),this._emitAssignmentLogEntries(l),l}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context);n=this._plugins.runBeforeDecision(n);let i=this._state.cachedEdgeResults??void 0,o=U(t,n,e.defaults,i);return this._cacheDecision(o),this._updateCumulativeAttribution(o),this._plugins.runDecision(o),this._emitAssignmentLogEntries(o),o},{decisionId:S(),assignments:e.defaults,metadata:{timestamp:new Date().toISOString(),unitKeyValue:"",layers:[]}})}trackExposure(e){this._errorBoundary.capture("trackExposure",()=>{let t=e.metadata.unitKeyValue;if(t){this._emitAssignmentLogEntries(e);for(let n of e.metadata.layers){if(!n.policyId||!n.allocationName||n.attributionOnly||!this._exposureDedup.checkAndMark(t,n.policyId,n.allocationName))continue;let o={type:"exposure",id:te(),decisionId:e.decisionId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:t,timestamp:new Date().toISOString(),assignments:e.assignments,layers:e.metadata.layers,context:e.metadata.filteredContext,sdkName:ce,sdkVersion:ue};this._plugins.runExposure(o)&&(this._disableCloudEvents||this._eventLogger.log(o))}}},void 0)}track(e,t,n){this._errorBoundary.capture("track",()=>{let i=n?.unitKey??this._stableId.getId(),o=typeof t?.value=="number"?t.value:void 0,s=this._buildAttribution(i,n?.decisionId),a=n?.decisionId,l={type:"track",id:ne(),orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:i,timestamp:new Date().toISOString(),event:e,value:o,properties:t,decisionId:a,attribution:s,sdkName:ce,sdkVersion:ue};this._plugins.runTrack(l)&&(this._disableCloudEvents||this._eventLogger.log(l))},void 0)}async flushEvents(){await this._errorBoundary.swallow("flushEvents",async()=>{await this._eventLogger.flush()})}use(e){return this._plugins.register(e),this}getPlugin(e){return this._plugins.get(e)}getStableId(){return this._stableId.getId()}setStableId(e){this._stableId.setId(e)}_emitAssignmentLogEntries(e){if(!this._assignmentLogger)return;let t=e.metadata.unitKeyValue;if(t)for(let n of e.metadata.layers)!n.policyId||!n.allocationName||this._assignmentLoggerDedup&&!this._assignmentLoggerDedup.checkAndMark(t,n.policyId,n.allocationName)||this._assignmentLogger({unitKey:t,policyId:n.policyId,policyKey:n.policyKey,allocationName:n.allocationName,allocationKey:n.allocationKey,timestamp:e.metadata.timestamp,layerId:n.layerId,allocationId:n.allocationId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,sdkName:ce,sdkVersion:ue,properties:e.metadata.filteredContext})}_getEffectiveBundle(){return this._state.bundle??this._options.localConfig??null}_enrichContext(e){let n=this._getEffectiveBundle()?.hashing?.unitKey??"userId";return e[n]?e:{...e,[n]:this._stableId.getId()}}async _fetchConfig(){let e=`${this._options.baseUrl}/v1/config/${this._options.projectId}?env=${this._options.env}`,t={"Content-Type":"application/json",Authorization:`Bearer ${this._options.apiKey}`};this._state.etag&&(t["If-None-Match"]=this._state.etag);try{let n=await fetch(e,{method:"GET",headers:t});if(n.status===304){this._state.lastFetchTime=Date.now();return}if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);let i=await n.json(),o=n.headers.get("ETag");if(this._state.bundle=i,this._state.etag=o,this._state.lastFetchTime=Date.now(),this._findEdgePolicies(i).length>0){let s=await this._prefetchEdgeResults(i,this._enrichContext({}));this._state.cachedEdgeResults=s}else this._state.cachedEdgeResults=null;this._plugins.runConfigUpdate(i)}catch(n){this._logOfflineWarning(n)}}_startBackgroundRefresh(){let e=this._options.evaluationMode==="server"?this._state.serverResponse?.suggestedRefreshMs??this._options.refreshIntervalMs:this._options.refreshIntervalMs;e<=0||(this._state.refreshTimer=setInterval(()=>{this._options.evaluationMode==="server"?this._fetchServerResolve().catch(()=>{}):this._fetchConfig().catch(()=>{})},e))}async _fetchServerResolve(){if(this._decisionClient)try{let e=this._enrichContext({}),t=await this._decisionClient.resolve({context:e});t&&(this._state.serverResponse=t,this._state.lastFetchTime=Date.now())}catch(e){this._logOfflineWarning(e)}}_findEdgePolicies(e){let t=[];for(let n of e.layers)for(let i of n.policies)i.state==="running"&&i.entityConfig?.resolutionMode==="edge"&&t.push(i);return t}async _prefetchEdgeResults(e,t){if(!this._decisionClient)return{};let n=this._findEdgePolicies(e);if(n.length===0)return{};let i=w(e,t);if(!i)return{};let o=n.map(s=>{if(!s.entityConfig)return null;let a=s.entityConfig.dynamicAllocations?typeof t[s.entityConfig.dynamicAllocations.countKey]=="number"?Math.floor(t[s.entityConfig.dynamicAllocations.countKey]):0:s.allocations.length;return ie(s.id,s.entityConfig.entityKeys,t,i,a||void 0)}).filter(s=>s!==null);if(o.length===0)return{};try{let s=await this._decisionClient.decideEntityBatch(o),a=new Map;for(let l=0;l<o.length;l++){let m=s[l];m&&a.set(o[l].policyId,{allocationIndex:m.allocationIndex,entityId:o[l].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>bt&&(console.warn(`[Traffical] Failed to fetch config: ${e instanceof Error?e.message:String(e)}. Using ${this._state.bundle?"cached":"local"} config.`),this._state.lastOfflineWarning=t)}_cacheDecision(e){if(this._decisionCache.size>=xt){let t=this._decisionCache.keys().next().value;t&&this._decisionCache.delete(t)}this._decisionCache.set(e.decisionId,e)}_updateCumulativeAttribution(e){let t=e.metadata.unitKeyValue;if(!t)return;let n=this._cumulativeAttribution.get(t);n||(n=new Map,this._cumulativeAttribution.set(t,n));for(let i of e.metadata.layers){if(!i.policyId||!i.allocationName)continue;let o=`${i.layerId}:${i.policyId}`;n.set(o,{layerId:i.layerId,policyId:i.policyId,allocationName:i.allocationName})}}_buildAttribution(e,t){if(this._options.attributionMode==="decision"){if(!t)return;let i=this._decisionCache.get(t);return i?i.metadata.layers.filter(o=>o.policyId&&o.allocationName).map(o=>({layerId:o.layerId,policyId:o.policyId,allocationName:o.allocationName})):void 0}let n=this._cumulativeAttribution.get(e);return n&&n.size>0?Array.from(n.values()):void 0}};async function ve(r){let e=new C(r);return await e.initialize(),e}function be(r){return new C(r)}function xe(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(c,d){try{return new RegExp(c).test(d)}catch{return d===c}}function a(c,d,h){if(d==="innerHTML")c.innerHTML=h;else if(d==="textContent")c.textContent=h;else if(d==="src"&&"src"in c)c.src=h;else if(d==="href"&&"href"in c)c.href=h;else if(d.startsWith("style.")){let f=d.slice(6);c.style[f]=h}else c.setAttribute(d,h)}function l(c,d){let h=String(d);try{let f=document.querySelectorAll(c.selector);for(let u of f)a(u,c.property,h)}catch(f){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${c.parameterKey}:`,f)}}function m(c,d=!1){n=c;let h=typeof window<"u"?window.location.pathname:"";for(let f of t){if(!d&&!s(f.urlPattern,h))continue;let u=c[f.parameterKey];u!==void 0&&l(f,u)}}function b(){o&&clearTimeout(o),o=setTimeout(()=>{m(n)},e.debounceMs)}function p(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{b()}),i.observe(document.body,{childList:!0,subtree:!0}))}function v(){i&&(i.disconnect(),i=null),o&&(clearTimeout(o),o=null)}return{name:"dom-binding",onInitialize(){e.observeMutations&&p()},onConfigUpdate(c){t=c.domBindings??[]},onResolve(c){m(c)},onDecision(c){m(c.assignments)},onDestroy(){v(),t=[],n={}},applyBindings(c){m(c||n)},getBindings(){return t}}}var _=null;async function It(r){return _?(console.warn("[Traffical] Client already initialized. Returning existing instance."),_):(_=await ve(r),_)}function Et(r){return _?(console.warn("[Traffical] Client already initialized. Returning existing instance."),_):(_=be(r),_.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),_)}function Tt(){return _}function kt(){_&&(_.destroy(),_=null)}return we(Ct);})();
1
+ /* @traffical/js-client v0.7.0 */
2
+ "use strict";var Traffical=(()=>{var B=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var Pe=Object.getOwnPropertyNames;var De=Object.prototype.hasOwnProperty;var Se=(r,e,t)=>e in r?B(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var we=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Ae=(r,e)=>{for(var t in e)B(r,t,{get:e[t],enumerable:!0})},Re=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Pe(e))!De.call(r,i)&&i!==t&&B(r,i,{get:()=>e[i],enumerable:!(n=Ce(e,i))||n.enumerable});return r};var Me=r=>Re(B({},"__esModule",{value:!0}),r);var I=(r,e,t)=>(Se(r,typeof e!="symbol"?e+"":e,t),t);var pe=we(()=>{});var Lt={};Ae(Lt,{TrafficalClient:()=>C,createDOMBindingPlugin:()=>ke,createDebugPlugin:()=>ue,createRedirectAttributionPlugin:()=>ce,createRedirectPlugin:()=>le,destroy:()=>Bt,init:()=>Rt,initSync:()=>Mt,instance:()=>Ot});function T(r){let e=2166136261;for(let t=0;t<r.length;t++)e^=r.charCodeAt(t),e=Math.imul(e,16777619);return e>>>0}function L(r,e,t){let n=`${r}:${e}`;return T(n)%t}function J(r,e){return r>=e[0]&&r<=e[1]}function N(r,e){for(let t of e)if(J(r,t.bucketRange))return t;return null}function k(r,e){if(r.length===0||r.length===1)return 0;let n=T(e)%1e4/1e4,i=0;for(let o=0;o<r.length;o++)if(i+=r[o],n<i)return o;return r.length-1}function Y(r,e){let{field:t,op:n,value:i,values:o}=r,s=Le(e,t);switch(n){case"eq":return s===i;case"neq":return s!==i;case"in":return Array.isArray(o)?o.includes(s):!1;case"nin":return Array.isArray(o)?!o.includes(s):!0;case"gt":return typeof s=="number"&&s>i;case"gte":return typeof s=="number"&&s>=i;case"lt":return typeof s=="number"&&s<i;case"lte":return typeof s=="number"&&s<=i;case"contains":return typeof s=="string"&&typeof i=="string"&&s.includes(i);case"startsWith":return typeof s=="string"&&typeof i=="string"&&s.startsWith(i);case"endsWith":return typeof s=="string"&&typeof i=="string"&&s.endsWith(i);case"regex":if(typeof s!="string"||typeof i!="string")return!1;try{return new RegExp(i).test(s)}catch{return!1}case"exists":return s!=null;case"notExists":return s==null;default:return!1}}function K(r,e){return r.length===0?!0:r.every(t=>Y(t,e))}function Le(r,e){let t=e.split("."),n=r;for(let i of t){if(n==null)return;if(typeof n=="object")n=n[i];else return}return n}function Z(r,e){let t=r.intercept;for(let{key:n,coef:i,missing:o}of r.numeric){let s=e[n];t+=typeof s=="number"?i*s:o}for(let{key:n,values:i,missing:o}of r.categorical){let s=e[n],a=s!=null?String(s):null;t+=a!==null&&a in i?i[a]:o}return t}function Q(r,e){if(r.length===0)return[];if(r.length===1)return[1];let t=Math.max(e,1e-10),n=r.map(a=>a/t),i=Math.max(...n),o=n.map(a=>Math.exp(a-i)),s=o.reduce((a,c)=>a+c,0);return o.map(a=>a/s)}function ee(r,e){if(r.length===0)return[];if(e<=0)return r;let t=r.length,n=1/t,i=Math.min(e,n),o=r.map(a=>Math.max(a,i)),s=o.reduce((a,c)=>a+c,0);return s===0?Array(t).fill(1/t):o.map(a=>a/s)}function V(r,e,t){let n=r.contextualModel;if(!n||r.allocations.length===0)return null;let i=Ne(n,r.allocations,e),o=Q(i,n.gamma),s=ee(o,n.actionProbabilityFloor),a=`ctx:${t}:${r.id}`,c=k(s,a);return r.allocations[c]}function Ne(r,e,t){return e.map(n=>{let i=r.coefficients[n.name];return i?Z(i,t):r.defaultAllocationScore})}var Ke=r=>crypto.getRandomValues(new Uint8Array(r)),Ve=(r,e,t)=>{let n=(2<<Math.log2(r.length-1))-1,i=-~(1.6*n*e/r.length);return(o=e)=>{let s="";for(;;){let a=t(i),c=i|0;for(;c--;)if(s+=r[a[c]&n]||"",s.length>=o)return s}}},ge=(r,e=21)=>Ve(r,e|0,Ke);function F(r){let e=new Error(r);return e.source="ulid",e}var te="0123456789ABCDEFGHJKMNPQRSTVWXYZ",P=te.length,he=Math.pow(2,48)-1,Fe=10,$e=16;function je(r){let e=Math.floor(r()*P);return e===P&&(e=P-1),te.charAt(e)}function Ue(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>he)throw F("cannot encode time greater than "+he);if(r<0)throw F("time must be positive");if(Number.isInteger(Number(r))===!1)throw F("time must be an integer");let t,n="";for(;e>0;e--)t=r%P,n=te.charAt(t)+n,r=(r-t)/P;return n}function ze(r,e){let t="";for(;r>0;r--)t=je(e)+t;return t}function We(r=!1,e){e||(e=typeof window<"u"?window:null);let t=e&&(e.crypto||e.msCrypto);if(t)return()=>{let n=new Uint8Array(1);return t.getRandomValues(n),n[0]/255};try{let n=pe();return()=>n.randomBytes(1).readUInt8()/255}catch{}if(r){try{console.error("secure crypto unusable, falling back to insecure Math.random()!")}catch{}return()=>Math.random()}throw F("secure crypto unusable, insecure Math.random not allowed")}function He(r){return r||(r=We()),function(t){return isNaN(t)&&(t=Date.now()),Ue(t,Fe)+ze($e,r)}}var me=He();var Ge="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",qe=8,nn=ge(Ge,qe);function $(r){return`${r}_${me()}`}function D(){return $("dec")}function ne(){return $("exp")}function ie(){return $("trk")}function Xe(r,e){let t=new Set;for(let i of e)if(i.contextLogging?.allowedFields)for(let o of i.contextLogging.allowedFields)t.add(o);if(t.size===0)return;let n={};for(let i of t)i in r&&(n[i]=r[i]);return Object.keys(n).length>0?n:void 0}function Je(r,e){let t=[];for(let n of r){let i=e[n];if(i==null)return null;t.push(String(i))}return t.join("_")}function ye(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function Ye(r,e,t,n){let i=r.entityState?.[e];if(!i)return ye(n);let o=i.entities[t];if(o&&o.weights.length===n)return o.weights;let s=i._global;return s&&s.weights.length===n?s.weights:ye(n)}function Ze(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=Je(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let h=i.dynamicAllocations.countKey,y=t[h];if(typeof y!="number"||y<=0)return null;a=Math.floor(y),s=Array.from({length:a},(d,f)=>({id:`${e.id}_dynamic_${f}`,name:String(f),bucketRange:[0,0],overrides:{}}))}else s=e.allocations,a=s.length;if(a===0)return null;let c=Ye(r,e.id,o,a),g=`${o}:${n}:${e.id}`,v=k(c,g);return{allocation:s[v],entityId:o}}function S(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function ve(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=S(r,e);if(!a)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let c=new Set(Object.keys(t)),g=r.parameters.filter(h=>c.has(h.key));for(let h of g)h.key in i&&(i[h.key]=h.default);let v=new Map;for(let h of g){let y=v.get(h.layerId)||[];y.push(h),v.set(h.layerId,y)}for(let h of r.layers){let y=v.get(h.id),d=y&&y.length>0,f=L(a,h.id,r.hashing.bucketCount),m,l;for(let u of h.policies)if(u.state==="running"){if(u.eligibleBucketRange){let{start:p,end:_}=u.eligibleBucketRange;if(f<p||f>_)continue}if(K(u.conditions,e)){if(u.contextualModel){let p=V(u,e,a);if(p){if(m=u,l=p,s.push(u),d)for(let[_,E]of Object.entries(p.overrides))_ in i&&(i[_]=E);break}}if(u.entityConfig&&u.entityConfig.resolutionMode==="bundle"){let p=Ze(r,u,e,a);if(p){if(m=u,l=p.allocation,s.push(u),d&&!u.entityConfig.dynamicAllocations)for(let[_,E]of Object.entries(p.allocation.overrides))_ in i&&(i[_]=E);break}}else if(u.entityConfig&&u.entityConfig.resolutionMode==="edge"){let p=n?.edgeResults?.get(u.id);if(p){if(m=u,s.push(u),u.entityConfig.dynamicAllocations)l={id:`${u.id}_dynamic_${p.allocationIndex}`,name:String(p.allocationIndex),bucketRange:[0,0],overrides:{}};else if(u.allocations[p.allocationIndex]&&(l=u.allocations[p.allocationIndex],d&&l))for(let[_,E]of Object.entries(l.overrides))_ in i&&(i[_]=E);break}continue}else{let p=N(f,u.allocations);if(p){if(m=u,l=p,s.push(u),d)for(let[_,E]of Object.entries(p.overrides))_ in i&&(i[_]=E);break}}}}o.push({layerId:h.id,bucket:f,policyId:m?.id,policyKey:m?.key,allocationId:l?.id,allocationName:l?.name,allocationKey:l?.key,...d?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function j(r,e,t,n){return ve(r,e,t,n).assignments}function U(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=ve(r,e,t,n),c=Xe(e,a);return{decisionId:D(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:c}}}var x=class r{constructor(e={}){I(this,"_seen",new Map);I(this,"_ttlMs");I(this,"_maxEntries");I(this,"_lastCleanup",Date.now());this._ttlMs=e.ttlMs??36e5,this._maxEntries=e.maxEntries??1e4}static hashAssignments(e){let t=Object.keys(e).sort(),n=[];for(let i of t){let o=e[i],s=typeof o=="object"?JSON.stringify(o):String(o);n.push(`${i}=${s}`)}return n.join("|")}static createKey(e,t){return`${e}:${t}`}checkAndMark(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o!==void 0&&i-o<this._ttlMs?!1:(this._seen.set(n,i),this._maybeCleanup(i),!0)}wouldBeNew(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o===void 0?!0:i-o>=this._ttlMs}clear(){this._seen.clear()}get size(){return this._seen.size}_maybeCleanup(e){(e-this._lastCleanup>this._ttlMs*.2||this._seen.size>this._maxEntries)&&(this._lastCleanup=e,this._cleanup(e))}_cleanup(e){let t=[];for(let[n,i]of this._seen.entries())e-i>=this._ttlMs&&t.push(n);for(let n of t)this._seen.delete(n);if(this._seen.size>this._maxEntries){let i=Array.from(this._seen.entries()).sort((o,s)=>o[1]-s[1]).slice(0,this._seen.size-this._maxEntries);for(let[o]of i)this._seen.delete(o)}}};var w=class{constructor(e){I(this,"config");I(this,"defaultTimeout");this.config=e,this.defaultTimeout=e.defaultTimeoutMs??5e3}async resolve(e){try{let t=new AbortController,n=setTimeout(()=>t.abort(),this.defaultTimeout),i=`${this.config.baseUrl}/v1/resolve`,o=await fetch(i,{method:"POST",headers:this._headers(),body:JSON.stringify({context:e.context,env:e.env??this.config.env,parameters:e.parameters}),signal:t.signal});return clearTimeout(n),o.ok?await o.json():(console.warn(`[Traffical] Resolve failed: ${o.status} ${o.statusText}`),null)}catch(t){return t instanceof Error&&t.name==="AbortError"?console.warn(`[Traffical] Resolve timed out after ${this.defaultTimeout}ms`):console.warn("[Traffical] Resolve error:",t),null}}async decideEntity(e,t){let n=t??Math.min(this.defaultTimeout,100);try{let i=new AbortController,o=setTimeout(()=>i.abort(),n),s=`${this.config.baseUrl}/v1/decide/${e.policyId}`,a=await fetch(s,{method:"POST",headers:this._headers(),body:JSON.stringify({entityId:e.entityId,unitKeyValue:e.unitKeyValue,allocationCount:e.allocationCount,context:e.context}),signal:i.signal});return clearTimeout(o),a.ok?await a.json():(console.warn(`[Traffical] Edge decide failed: ${a.status} ${a.statusText}`),null)}catch(i){return i instanceof Error&&i.name==="AbortError"?console.warn(`[Traffical] Edge decide timed out after ${n}ms`):console.warn("[Traffical] Edge decide error:",i),null}}async decideEntityBatch(e,t){if(e.length===0)return[];if(e.length===1)return[await this.decideEntity(e[0],t)];let n=t??Math.min(this.defaultTimeout,200);try{let i=new AbortController,o=setTimeout(()=>i.abort(),n),s=`${this.config.baseUrl}/v1/decide/batch`,a=await fetch(s,{method:"POST",headers:this._headers(),body:JSON.stringify({requests:e}),signal:i.signal});return clearTimeout(o),a.ok?(await a.json()).responses:(console.warn(`[Traffical] Edge batch decide failed: ${a.status} ${a.statusText}`),e.map(()=>null))}catch(i){return i instanceof Error&&i.name==="AbortError"?console.warn(`[Traffical] Edge batch decide timed out after ${n}ms`):console.warn("[Traffical] Edge batch decide error:",i),e.map(()=>null)}}_headers(){return{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`,"X-Org-Id":this.config.orgId,"X-Project-Id":this.config.projectId,"X-Env":this.config.env}}};function re(r,e,t,n,i){let o=[];for(let a of e){let c=t[a];if(c==null)return null;o.push(String(c))}let s=o.join("_");return{policyId:r,entityId:s,unitKeyValue:n,allocationCount:i,context:t}}var z=class{constructor(e={}){this._seen=new Set;this._lastError=null;this._options=e}capture(e,t,n){try{return t()}catch(i){return this._onError(e,i),n}}async captureAsync(e,t,n){try{return await t()}catch(i){return this._onError(e,i),n}}async swallow(e,t){try{await t()}catch(n){this._onError(e,n)}}getLastError(){let e=this._lastError;return this._lastError=null,e}clearSeen(){this._seen.clear()}_onError(e,t){let n=this._resolveError(t);this._lastError=n;let i=`${e}:${n.name}:${n.message}`;this._seen.has(i)||(this._seen.add(i),console.warn(`[Traffical] Error in ${e}:`,n.message),this._options.onError?.(e,n),this._options.reportErrors&&this._options.errorEndpoint&&this._reportError(e,n).catch(()=>{}))}async _reportError(e,t){if(this._options.errorEndpoint)try{await fetch(this._options.errorEndpoint,{method:"POST",headers:{"Content-Type":"application/json",...this._options.sdkKey&&{"X-Traffical-Key":this._options.sdkKey}},body:JSON.stringify({tag:e,error:t.name,message:t.message,stack:t.stack,timestamp:new Date().toISOString(),sdk:"@traffical/js-client",userAgent:typeof navigator<"u"?navigator.userAgent:void 0})})}catch{}}_resolveError(e){return e instanceof Error?e:typeof e=="string"?new Error(e):new Error("An unknown error occurred")}};var W="failed_events";var H=class{constructor(e){this._queue=[];this._flushTimer=null;this._isFlushing=!1;this._endpoint=e.endpoint,this._apiKey=e.apiKey,this._storage=e.storage,this._batchSize=e.batchSize??10,this._flushIntervalMs=e.flushIntervalMs??3e4,this._onError=e.onError,this._lifecycleProvider=e.lifecycleProvider,this._setupListeners(),this._retryFailedEvents(),this._startFlushTimer()}log(e){this._queue.push(e),this._queue.length>=this._batchSize&&this.flush()}async flush(){if(this._isFlushing||this._queue.length===0)return;this._isFlushing=!0;let e=[...this._queue];this._queue=[];try{await this._sendEvents(e)}catch(t){this._persistFailedEvents(e),this._onError?.(t instanceof Error?t:new Error(String(t)))}finally{this._isFlushing=!1}}flushBeacon(){if(this._queue.length===0)return!0;if(typeof fetch>"u")return this.flush(),!1;let e=[...this._queue];return this._queue=[],fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e}),keepalive:!0}).catch(()=>{this._persistFailedEvents(e)}),!0}get queueSize(){return this._queue.length}destroy(){this._flushTimer&&(clearInterval(this._flushTimer),this._flushTimer=null),this._removeListeners()}async _sendEvents(e){let t=await fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e})});if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`)}_persistFailedEvents(e){let n=[...this._storage.get(W)??[],...e].slice(-100);this._storage.set(W,n)}_retryFailedEvents(){let e=this._storage.get(W);!e||e.length===0||(this._storage.remove(W),this._queue.push(...e))}_startFlushTimer(){this._flushIntervalMs<=0||(this._flushTimer=setInterval(()=>{this.flush().catch(()=>{})},this._flushIntervalMs))}_setupListeners(){this._lifecycleProvider&&(this._visibilityCallback=e=>{e==="background"?this._lifecycleProvider?.isUnloading()?this.flushBeacon():this.flush().catch(()=>{}):this._retryFailedEvents()},this._lifecycleProvider.onVisibilityChange(this._visibilityCallback))}_removeListeners(){this._lifecycleProvider&&this._visibilityCallback&&(this._lifecycleProvider.removeVisibilityListener(this._visibilityCallback),this._visibilityCallback=void 0)}};var A="exposure_dedup";var R=class r{constructor(e){this._storage=e.storage,this._sessionTtlMs=e.sessionTtlMs??18e5,this._seen=new Set,this._sessionStart=Date.now(),this._restore()}static createKey(e,t,n){return`${e}:${t}:${n}`}shouldTrack(e){return this._isSessionExpired()&&this._resetSession(),this._seen.has(e)?!1:(this._seen.add(e),this._persist(),!0)}checkAndMark(e,t,n){let i=r.createKey(e,t,n);return this.shouldTrack(i)}clear(){this._seen.clear(),this._storage.remove(A)}get size(){return this._seen.size}_isSessionExpired(){return Date.now()-this._sessionStart>this._sessionTtlMs}_resetSession(){this._seen.clear(),this._sessionStart=Date.now(),this._storage.remove(A)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(A,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(A);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(A);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var M="stable_id",gt="traffical_sid";var G=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??gt}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(M);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(M,e),this._cachedId=e,e):(e=this._generateId(),this._persist(e),this._cachedId=e,e)}setId(e){this._persist(e),this._cachedId=e}clear(){this._storage.remove(M),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(M)!==null||this._getCookie()!==null}_persist(e){this._storage.set(M,e),this._useCookieFallback&&this._setCookie(e)}_generateId(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}_getCookie(){if(typeof document>"u")return null;try{let e=document.cookie.split(";");for(let t of e){let[n,i]=t.trim().split("=");if(n===this._cookieName&&i)return decodeURIComponent(i)}}catch{}return null}_setCookie(e){if(!(typeof document>"u"))try{document.cookie=`${this._cookieName}=${encodeURIComponent(e)}; max-age=31536000; path=/; SameSite=Lax`}catch{}}_deleteCookie(){if(!(typeof document>"u"))try{document.cookie=`${this._cookieName}=; max-age=0; path=/`}catch{}}};var O="traffical:",oe=class{constructor(){this._available=this._checkAvailability()}get(e){if(!this._available)return null;try{let t=localStorage.getItem(O+e);if(!t)return null;let n=JSON.parse(t);return n.expiresAt&&Date.now()>n.expiresAt?(this.remove(e),null):n.value}catch{return null}}set(e,t,n){if(this._available)try{let i={value:t,...n&&{expiresAt:Date.now()+n}};localStorage.setItem(O+e,JSON.stringify(i))}catch{}}remove(e){if(this._available)try{localStorage.removeItem(O+e)}catch{}}clear(){if(this._available)try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n?.startsWith(O)&&e.push(n)}e.forEach(t=>localStorage.removeItem(t))}catch{}}_checkAvailability(){try{let e=O+"__test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}},se=class{constructor(){this._store=new Map}get(e){let t=this._store.get(e);return t?t.expiresAt&&Date.now()>t.expiresAt?(this.remove(e),null):t.value:null}set(e,t,n){this._store.set(e,{value:t,...n&&{expiresAt:Date.now()+n}})}remove(e){this._store.delete(e)}clear(){this._store.clear()}};function _e(){let r=new oe;return r.get("__check__")!==null||pt()?r:new se}function pt(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var ht="js-client",mt="0.1.0";function ae(r,e){let t=new x({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=x.hashAssignments(n.assignments);if(!t.checkAndMark(i,o))return;let s={type:"decision",id:n.decisionId,orgId:e.orgId,projectId:e.projectId,env:e.env,unitKey:i,timestamp:n.metadata.timestamp,assignments:n.assignments,layers:n.metadata.layers,context:n.metadata.filteredContext,sdkName:ht,sdkVersion:mt};e.log(s)},onDestroy(){t.clear()}}}var yt="traffical_rdr";function vt(r,e,t){if(!(typeof document>"u"))try{document.cookie=`${r}=${encodeURIComponent(e)}; max-age=${t}; path=/; SameSite=Lax`}catch{}}function le(r={}){let e=r.parameterKey??"redirect.url",t=r.compareMode??"pathname",n=r.cookieName??yt;return{name:"redirect",onInitialize(i){typeof window>"u"||i.decide({context:{},defaults:{[e]:""}})},onBeforeDecision(i){return typeof window>"u"?i:{"url.pathname":window.location.pathname,...i}},onDecision(i){let o=i.assignments[e];if(typeof o!="string"||!o)return;let s=t==="href"?window.location.href:window.location.pathname;if(o===s)return;let a=i.metadata.layers.find(c=>c.policyId&&c.allocationName);a&&vt(n,JSON.stringify({l:a.layerId,p:a.policyId,a:a.allocationName,ts:Date.now()}),86400),window.location.replace(o)}}}var _t="traffical_rdr";function bt(r){if(typeof document>"u")return null;try{for(let e of document.cookie.split(";")){let[t,n]=e.trim().split("=");if(t===r&&n)return decodeURIComponent(n)}}catch{}return null}function It(r,e){let t=bt(r);if(!t)return null;try{let n=JSON.parse(t);return Date.now()-n.ts>e?null:{layerId:n.l,policyId:n.p,allocationName:n.a}}catch{return null}}function ce(r={}){let e=r.cookieName??_t,t=r.expiryMs??864e5;function n(i){let o=It(e,t);if(!o)return;i.attribution=i.attribution??[],i.attribution.some(a=>a.layerId===o.layerId&&a.policyId===o.policyId)||i.attribution.push(o)}return{name:"redirect-attribution",onTrack(i){return n(i),!0},onExposure(i){return n(i),!0}}}var q=[],be={};function Et(){if(typeof window>"u")return{version:1,instances:be,subscribe:()=>()=>{}};if(!window.__TRAFFICAL_DEBUG__){let r={version:1,instances:be,subscribe(e){return q.push(e),()=>{q=q.filter(t=>t!==e)}}};window.__TRAFFICAL_DEBUG__=r}return window.__TRAFFICAL_DEBUG__}function Ie(r){for(let e of q)try{e(r)}catch{}}var xt=0;function Tt(){return`traffical_${Date.now().toString(36)}_${(++xt).toString(36)}`}function kt(){return`evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}var Ct="traffical-debug",Pt="__SDK_VERSION__";function ue(r={}){let e=r.instanceId??Tt(),t=r.maxEvents??500,n=null,i=null,o={},s=[],a=null,c=[],g=[],v=[];function h(){return{ready:n?.isInitialized===!0,stableId:n?.getStableId?.()??null,configVersion:n?.getConfigVersion?.()??null,assignments:{...o},layers:[...s],lastDecisionId:a}}function y(){let l=h();for(let u of g)try{u(l)}catch{}}function d(l,u){let p={id:kt(),type:l,timestamp:Date.now(),data:u};c.push(p),c.length>t&&c.splice(0,c.length-t);for(let _ of v)try{_(p)}catch{}}let f={id:e,meta:{orgId:"",projectId:"",env:"",sdkVersion:Pt},getState:h,subscribe(l){return g.push(l),()=>{g=g.filter(u=>u!==l)}},getEvents(l){return l!==void 0?c.slice(-l):[...c]},onEvent(l){return v.push(l),()=>{v=v.filter(u=>u!==l)}},getConfigBundle(){return i},setUnitKey(l){n?.setStableId&&(n.setStableId(l),y())},reDecide(){if(n)try{n.decide({context:{},defaults:{}})}catch{}},async refresh(){n?.refreshConfig&&await n.refreshConfig()}};return{name:Ct,onInitialize(l){n=l,i&&(f.meta.orgId=i.orgId,f.meta.projectId=i.projectId,f.meta.env=i.env);let u=Et();u.instances[e]=f,Ie({type:"register",instanceId:e}),y()},onConfigUpdate(l){i=l,f.meta.orgId=l.orgId,f.meta.projectId=l.projectId,f.meta.env=l.env,y()},onDecision(l){o={...l.assignments},s=l.metadata?.layers?[...l.metadata.layers]:[],a=l.decisionId,d("decision",l),y()},onResolve(l){o={...l},y()},onExposure(l){return d("exposure",l),!0},onTrack(l){return d("track",l),!0},onDestroy(){let l=typeof window<"u"?window.__TRAFFICAL_DEBUG__:null;l&&(delete l.instances[e],Ie({type:"unregister",instanceId:e})),g=[],v=[],n=null}}}var X=class{constructor(){this._plugins=[]}register(e){let t="plugin"in e?e.plugin:e,n="priority"in e?e.priority??0:0;if(this._plugins.some(i=>i.plugin.name===t.name)){console.warn(`[Traffical] Plugin "${t.name}" already registered, skipping.`);return}this._plugins.push({plugin:t,priority:n}),this._plugins.sort((i,o)=>o.priority-i.priority)}unregister(e){let t=this._plugins.findIndex(n=>n.plugin.name===e);return t===-1?!1:(this._plugins.splice(t,1),!0)}get(e){return this._plugins.find(t=>t.plugin.name===e)?.plugin}getAll(){return this._plugins.map(e=>e.plugin)}async runInitialize(e){for(let{plugin:t}of this._plugins)if(t.onInitialize)try{await t.onInitialize(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onInitialize error:`,n)}}runConfigUpdate(e){for(let{plugin:t}of this._plugins)if(t.onConfigUpdate)try{t.onConfigUpdate(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onConfigUpdate error:`,n)}}runBeforeDecision(e){let t=e;for(let{plugin:n}of this._plugins)if(n.onBeforeDecision)try{let i=n.onBeforeDecision(t);i&&(t=i)}catch(i){console.warn(`[Traffical] Plugin "${n.name}" onBeforeDecision error:`,i)}return t}runDecision(e){for(let{plugin:t}of this._plugins)if(t.onDecision)try{t.onDecision(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onDecision error:`,n)}}runResolve(e){for(let{plugin:t}of this._plugins)if(t.onResolve)try{t.onResolve(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onResolve error:`,n)}}runExposure(e){for(let{plugin:t}of this._plugins)if(t.onExposure)try{if(t.onExposure(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onExposure error:`,n)}return!0}runTrack(e){for(let{plugin:t}of this._plugins)if(t.onTrack)try{if(t.onTrack(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onTrack error:`,n)}return!0}runDestroy(){for(let{plugin:e}of this._plugins)if(e.onDestroy)try{e.onDestroy()}catch(t){console.warn(`[Traffical] Plugin "${e.name}" onDestroy error:`,t)}}clear(){this._plugins=[]}};function Ee(){let r=[],e=!1;function t(s){for(let a of r)a(s)}let n=()=>{e=!0,t("background")},i=()=>{typeof document<"u"&&t(document.visibilityState==="hidden"?"background":"foreground")},o=()=>{e=!0,t("background")};return typeof window<"u"&&(window.addEventListener("pagehide",n),window.addEventListener("beforeunload",o)),typeof document<"u"&&document.addEventListener("visibilitychange",i),{onVisibilityChange(s){r.push(s)},removeVisibilityListener(s){let a=r.indexOf(s);a!==-1&&r.splice(a,1)},isUnloading(){return e}}}var de="js-client",fe="0.1.0",Dt="https://sdk.traffical.io",St=6e4,wt=3e5,At=100,C=class{constructor(e){this._state={bundle:null,etag:null,lastFetchTime:0,lastOfflineWarning:0,refreshTimer:null,isInitialized:!1,serverResponse:null,cachedEdgeResults:null};this._decisionCache=new Map;this._cumulativeAttribution=new Map;let t=e.evaluationMode??"bundle";this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??Dt,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??St,attributionMode:e.attributionMode??"cumulative",evaluationMode:t};let n={baseUrl:this._options.baseUrl,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,apiKey:this._options.apiKey};if(this._decisionClient=new w(n),this._errorBoundary=new z(e.errorBoundary),this._storage=e.storage??_e(),this._lifecycleProvider=e.lifecycleProvider??Ee(),this._eventLogger=new H({endpoint:`${this._options.baseUrl}/v1/events/batch`,apiKey:e.apiKey,storage:this._storage,lifecycleProvider:this._lifecycleProvider,batchSize:e.eventBatchSize,flushIntervalMs:e.eventFlushIntervalMs,onError:i=>{console.warn("[Traffical] Event logging error:",i.message)}}),this._exposureDedup=new R({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new G({storage:this._storage}),this._plugins=new X,this._assignmentLogger=e.assignmentLogger,this._disableCloudEvents=e.disableCloudEvents??!1,this._assignmentLoggerDedup=e.deduplicateAssignmentLogger!==!1&&e.assignmentLogger?new R({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}):null,e.trackDecisions!==!1&&!this._disableCloudEvents&&this._plugins.register({plugin:ae({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:i=>this._eventLogger.log(i)}),priority:100}),e.plugins)for(let i of e.plugins)this._plugins.register(i);this._options.localConfig&&(this._state.bundle=this._options.localConfig,this._plugins.runConfigUpdate(this._options.localConfig))}async initialize(){await this._errorBoundary.captureAsync("initialize",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig(),this._startBackgroundRefresh(),this._state.isInitialized=!0,await this._plugins.runInitialize(this)},void 0)}get isInitialized(){return this._state.isInitialized}destroy(){this._state.refreshTimer&&(clearInterval(this._state.refreshTimer),this._state.refreshTimer=null),this._lifecycleProvider.isUnloading()?this._eventLogger.flushBeacon():this._eventLogger.flush().catch(()=>{}),this._eventLogger.destroy(),this._plugins.runDestroy()}async refreshConfig(){await this._errorBoundary.swallow("refreshConfig",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig()})}getConfigVersion(){return this._state.serverResponse?.stateVersion??this._state.bundle?.version??null}getParams(e){return this._errorBoundary.capture("getParams",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let o={...e.defaults};for(let[s,a]of Object.entries(this._state.serverResponse.assignments))s in o&&(o[s]=a);return this._plugins.runResolve(o),o}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context),i=j(t,n,e.defaults);return this._plugins.runResolve(i),i},e.defaults)}decide(e){return this._errorBoundary.capture("decide",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let s=this._state.serverResponse,a={...e.defaults};for(let[g,v]of Object.entries(s.assignments))g in a&&(a[g]=v);let c={decisionId:s.decisionId,assignments:a,metadata:s.metadata};return this._cacheDecision(c),this._updateCumulativeAttribution(c),this._plugins.runDecision(c),this._emitAssignmentLogEntries(c),c}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context);n=this._plugins.runBeforeDecision(n);let i=this._state.cachedEdgeResults??void 0,o=U(t,n,e.defaults,i);return this._cacheDecision(o),this._updateCumulativeAttribution(o),this._plugins.runDecision(o),this._emitAssignmentLogEntries(o),o},{decisionId:D(),assignments:e.defaults,metadata:{timestamp:new Date().toISOString(),unitKeyValue:"",layers:[]}})}trackExposure(e){this._errorBoundary.capture("trackExposure",()=>{let t=e.metadata.unitKeyValue;if(t){this._emitAssignmentLogEntries(e);for(let n of e.metadata.layers){if(!n.policyId||!n.allocationName||n.attributionOnly||!this._exposureDedup.checkAndMark(t,n.policyId,n.allocationName))continue;let o={type:"exposure",id:ne(),decisionId:e.decisionId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:t,timestamp:new Date().toISOString(),assignments:e.assignments,layers:e.metadata.layers,context:e.metadata.filteredContext,sdkName:de,sdkVersion:fe};this._plugins.runExposure(o)&&(this._disableCloudEvents||this._eventLogger.log(o))}}},void 0)}track(e,t,n){this._errorBoundary.capture("track",()=>{let i=n?.unitKey??this._stableId.getId(),o=typeof t?.value=="number"?t.value:void 0,s=this._buildAttribution(i,n?.decisionId),a=n?.decisionId,c={type:"track",id:ie(),orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:i,timestamp:new Date().toISOString(),event:e,value:o,properties:t,decisionId:a,attribution:s,sdkName:de,sdkVersion:fe};this._plugins.runTrack(c)&&(this._disableCloudEvents||this._eventLogger.log(c))},void 0)}async flushEvents(){await this._errorBoundary.swallow("flushEvents",async()=>{await this._eventLogger.flush()})}use(e){return this._plugins.register(e),this}getPlugin(e){return this._plugins.get(e)}getStableId(){return this._stableId.getId()}setStableId(e){this._stableId.setId(e)}_emitAssignmentLogEntries(e){if(!this._assignmentLogger)return;let t=e.metadata.unitKeyValue;if(t)for(let n of e.metadata.layers)!n.policyId||!n.allocationName||this._assignmentLoggerDedup&&!this._assignmentLoggerDedup.checkAndMark(t,n.policyId,n.allocationName)||this._assignmentLogger({unitKey:t,policyId:n.policyId,policyKey:n.policyKey,allocationName:n.allocationName,allocationKey:n.allocationKey,timestamp:e.metadata.timestamp,layerId:n.layerId,allocationId:n.allocationId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,sdkName:de,sdkVersion:fe,properties:e.metadata.filteredContext})}_getEffectiveBundle(){return this._state.bundle??this._options.localConfig??null}_enrichContext(e){let n=this._getEffectiveBundle()?.hashing?.unitKey??"userId";return e[n]?e:{...e,[n]:this._stableId.getId()}}async _fetchConfig(){let e=`${this._options.baseUrl}/v1/config/${this._options.projectId}?env=${this._options.env}`,t={"Content-Type":"application/json",Authorization:`Bearer ${this._options.apiKey}`};this._state.etag&&(t["If-None-Match"]=this._state.etag);try{let n=await fetch(e,{method:"GET",headers:t});if(n.status===304){this._state.lastFetchTime=Date.now();return}if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);let i=await n.json(),o=n.headers.get("ETag");if(this._state.bundle=i,this._state.etag=o,this._state.lastFetchTime=Date.now(),this._findEdgePolicies(i).length>0){let s=await this._prefetchEdgeResults(i,this._enrichContext({}));this._state.cachedEdgeResults=s}else this._state.cachedEdgeResults=null;this._plugins.runConfigUpdate(i)}catch(n){this._logOfflineWarning(n)}}_startBackgroundRefresh(){let e=this._options.evaluationMode==="server"?this._state.serverResponse?.suggestedRefreshMs??this._options.refreshIntervalMs:this._options.refreshIntervalMs;e<=0||(this._state.refreshTimer=setInterval(()=>{this._options.evaluationMode==="server"?this._fetchServerResolve().catch(()=>{}):this._fetchConfig().catch(()=>{})},e))}async _fetchServerResolve(){if(this._decisionClient)try{let e=this._enrichContext({}),t=await this._decisionClient.resolve({context:e});t&&(this._state.serverResponse=t,this._state.lastFetchTime=Date.now())}catch(e){this._logOfflineWarning(e)}}_findEdgePolicies(e){let t=[];for(let n of e.layers)for(let i of n.policies)i.state==="running"&&i.entityConfig?.resolutionMode==="edge"&&t.push(i);return t}async _prefetchEdgeResults(e,t){if(!this._decisionClient)return{};let n=this._findEdgePolicies(e);if(n.length===0)return{};let i=S(e,t);if(!i)return{};let o=n.map(s=>{if(!s.entityConfig)return null;let a=s.entityConfig.dynamicAllocations?typeof t[s.entityConfig.dynamicAllocations.countKey]=="number"?Math.floor(t[s.entityConfig.dynamicAllocations.countKey]):0:s.allocations.length;return re(s.id,s.entityConfig.entityKeys,t,i,a||void 0)}).filter(s=>s!==null);if(o.length===0)return{};try{let s=await this._decisionClient.decideEntityBatch(o),a=new Map;for(let c=0;c<o.length;c++){let g=s[c];g&&a.set(o[c].policyId,{allocationIndex:g.allocationIndex,entityId:o[c].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>wt&&(console.warn(`[Traffical] Failed to fetch config: ${e instanceof Error?e.message:String(e)}. Using ${this._state.bundle?"cached":"local"} config.`),this._state.lastOfflineWarning=t)}_cacheDecision(e){if(this._decisionCache.size>=At){let t=this._decisionCache.keys().next().value;t&&this._decisionCache.delete(t)}this._decisionCache.set(e.decisionId,e)}_updateCumulativeAttribution(e){let t=e.metadata.unitKeyValue;if(!t)return;let n=this._cumulativeAttribution.get(t);n||(n=new Map,this._cumulativeAttribution.set(t,n));for(let i of e.metadata.layers){if(!i.policyId||!i.allocationName)continue;let o=`${i.layerId}:${i.policyId}`;n.set(o,{layerId:i.layerId,policyId:i.policyId,allocationName:i.allocationName})}}_buildAttribution(e,t){if(this._options.attributionMode==="decision"){if(!t)return;let i=this._decisionCache.get(t);return i?i.metadata.layers.filter(o=>o.policyId&&o.allocationName).map(o=>({layerId:o.layerId,policyId:o.policyId,allocationName:o.allocationName})):void 0}let n=this._cumulativeAttribution.get(e);return n&&n.size>0?Array.from(n.values()):void 0}};async function xe(r){let e=new C(r);return await e.initialize(),e}function Te(r){return new C(r)}function ke(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(d,f){try{return new RegExp(d).test(f)}catch{return f===d}}function a(d,f,m){if(f==="innerHTML")d.innerHTML=m;else if(f==="textContent")d.textContent=m;else if(f==="src"&&"src"in d)d.src=m;else if(f==="href"&&"href"in d)d.href=m;else if(f.startsWith("style.")){let l=f.slice(6);d.style[l]=m}else d.setAttribute(f,m)}function c(d,f){let m=String(f);try{let l=document.querySelectorAll(d.selector);for(let u of l)a(u,d.property,m)}catch(l){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${d.parameterKey}:`,l)}}function g(d,f=!1){n=d;let m=typeof window<"u"?window.location.pathname:"";for(let l of t){if(!f&&!s(l.urlPattern,m))continue;let u=d[l.parameterKey];u!==void 0&&c(l,u)}}function v(){o&&clearTimeout(o),o=setTimeout(()=>{g(n)},e.debounceMs)}function h(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{v()}),i.observe(document.body,{childList:!0,subtree:!0}))}function y(){i&&(i.disconnect(),i=null),o&&(clearTimeout(o),o=null)}return{name:"dom-binding",onInitialize(){e.observeMutations&&h()},onConfigUpdate(d){t=d.domBindings??[]},onResolve(d){g(d)},onDecision(d){g(d.assignments)},onDestroy(){y(),t=[],n={}},applyBindings(d){g(d||n)},getBindings(){return t}}}var b=null;async function Rt(r){return b?(console.warn("[Traffical] Client already initialized. Returning existing instance."),b):(b=await xe(r),b)}function Mt(r){return b?(console.warn("[Traffical] Client already initialized. Returning existing instance."),b):(b=Te(r),b.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),b)}function Ot(){return b}function Bt(){b&&(b.destroy(),b=null)}return Me(Lt);})();
3
3
  //# sourceMappingURL=traffical.min.js.map