@traffical/js-client 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/traffical.min.js +1 -1
- package/package.json +1 -1
package/dist/traffical.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/* @traffical/js-client v0.1.
|
|
1
|
+
/* @traffical/js-client v0.1.3 */
|
|
2
2
|
"use strict";var Traffical=(()=>{var w=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var fe=Object.prototype.hasOwnProperty;var ge=(r,e,t)=>e in r?w(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var pe=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),he=(r,e)=>{for(var t in e)w(r,t,{get:e[t],enumerable:!0})},me=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of de(e))!fe.call(r,i)&&i!==t&&w(r,i,{get:()=>e[i],enumerable:!(n=ce(e,i))||n.enumerable});return r};var ye=r=>me(w({},"__esModule",{value:!0}),r);var E=(r,e,t)=>(ge(r,typeof e!="symbol"?e+"":e,t),t);var Q=pe(()=>{});var dt={};he(dt,{TrafficalClient:()=>T,createDOMBindingPlugin:()=>ue,destroy:()=>ct,init:()=>at,initSync:()=>lt,instance:()=>ut});function x(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 S(r,e,t){let n=`${r}:${e}`;return x(n)%t}function U(r,e){return r>=e[0]&&r<=e[1]}function P(r,e){for(let t of e)if(U(r,t.bucketRange))return t;return null}function z(r,e){let{field:t,op:n,value:i,values:o}=r,s=Ee(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 B(r,e){return r.length===0?!0:r.every(t=>z(t,e))}function Ee(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}var xe=r=>crypto.getRandomValues(new Uint8Array(r)),Te=(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 f=t(i),h=i|0;for(;h--;)if(s+=r[f[h]&n]||"",s.length>=o)return s}}},Z=(r,e=21)=>Te(r,e|0,xe);function A(r){let e=new Error(r);return e.source="ulid",e}var q="0123456789ABCDEFGHJKMNPQRSTVWXYZ",b=q.length,ee=Math.pow(2,48)-1,be=10,Ie=16;function Ce(r){let e=Math.floor(r()*b);return e===b&&(e=b-1),q.charAt(e)}function De(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>ee)throw A("cannot encode time greater than "+ee);if(r<0)throw A("time must be positive");if(Number.isInteger(Number(r))===!1)throw A("time must be an integer");let t,n="";for(;e>0;e--)t=r%b,n=q.charAt(t)+n,r=(r-t)/b;return n}function ke(r,e){let t="";for(;r>0;r--)t=Ce(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=Q();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 A("secure crypto unusable, insecure Math.random not allowed")}function Se(r){return r||(r=we()),function(t){return isNaN(t)&&(t=Date.now()),De(t,be)+ke(Ie,r)}}var te=Se();var Pe="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Be=8,Dt=Z(Pe,Be);function R(r){return`${r}_${te()}`}function I(){return R("dec")}function W(){return R("exp")}function H(){return R("trk")}function Ae(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 Re(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 Me(r,e){if(r.length===0||r.length===1)return 0;let n=x(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 ne(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function Oe(r,e,t,n){let i=r.entityState?.[e];if(!i)return ne(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:ne(n)}function Ne(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=Re(i.entityKeys,t);if(!o)return null;let s,f;if(i.dynamicAllocations){let _=i.dynamicAllocations.countKey,y=t[_];if(typeof y!="number"||y<=0)return null;f=Math.floor(y),s=Array.from({length:f},(a,c)=>({id:`${e.id}_dynamic_${c}`,name:String(c),bucketRange:[0,0],overrides:{}}))}else s=e.allocations,f=s.length;if(f===0)return null;let h=Oe(r,e.id,o,f),g=`${o}:${n}:${e.id}`,u=Me(h,g);return{allocation:s[u],entityId:o}}function X(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function re(r,e,t){let n={...t},i=[],o=[];if(!r)return{assignments:n,unitKeyValue:"",layers:i,matchedPolicies:o};let s=X(r,e);if(!s)return{assignments:n,unitKeyValue:"",layers:i,matchedPolicies:o};let f=new Set(Object.keys(t)),h=r.parameters.filter(u=>f.has(u.key));for(let u of h)u.key in n&&(n[u.key]=u.default);let g=new Map;for(let u of h){let _=g.get(u.layerId)||[];_.push(u),g.set(u.layerId,_)}for(let u of r.layers){let _=g.get(u.id);if(!_||_.length===0)continue;let y=S(s,u.id,r.hashing.bucketCount),a,c;for(let l of u.policies)if(l.state==="running"){if(l.eligibleBucketRange){let{start:d,end:m}=l.eligibleBucketRange;if(y<d||y>m)continue}if(B(l.conditions,e))if(l.entityConfig&&l.entityConfig.resolutionMode==="bundle"){let d=Ne(r,l,e,s);if(d){if(a=l,c=d.allocation,o.push(l),!l.entityConfig.dynamicAllocations)for(let[m,$]of Object.entries(d.allocation.overrides))m in n&&(n[m]=$);break}}else{if(l.entityConfig&&l.entityConfig.resolutionMode==="edge")continue;{let d=P(y,l.allocations);if(d){a=l,c=d,o.push(l);for(let[m,$]of Object.entries(d.overrides))m in n&&(n[m]=$);break}}}}i.push({layerId:u.id,bucket:y,policyId:a?.id,allocationId:c?.id,allocationName:c?.name})}return{assignments:n,unitKeyValue:s,layers:i,matchedPolicies:o}}function M(r,e,t){return re(r,e,t).assignments}function O(r,e,t){let{assignments:n,unitKeyValue:i,layers:o,matchedPolicies:s}=re(r,e,t),f=Ae(e,s);return{decisionId:I(),assignments:n,metadata:{timestamp:new Date().toISOString(),unitKeyValue:i,layers:o,filteredContext:f}}}var v=class r{constructor(e={}){E(this,"_seen",new Map);E(this,"_ttlMs");E(this,"_maxEntries");E(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 N=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 L="failed_events";var K=class{constructor(e){this._queue=[];this._flushTimer=null;this._isFlushing=!1;this._onPageHide=()=>{this.flushBeacon()};this._onVisibilityChange=()=>{document.visibilityState==="hidden"&&this.flushBeacon()};this._onBeforeUnload=()=>{this.flushBeacon()};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._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(L)??[],...e].slice(-100);this._storage.set(L,n)}_retryFailedEvents(){let e=this._storage.get(L);!e||e.length===0||(this._storage.remove(L),this._queue.push(...e))}_startFlushTimer(){this._flushIntervalMs<=0||(this._flushTimer=setInterval(()=>{this.flush().catch(()=>{})},this._flushIntervalMs))}_setupListeners(){typeof window>"u"||(window.addEventListener("pagehide",this._onPageHide),document.addEventListener("visibilitychange",this._onVisibilityChange),window.addEventListener("beforeunload",this._onBeforeUnload))}_removeListeners(){typeof window>"u"||(window.removeEventListener("pagehide",this._onPageHide),document.removeEventListener("visibilitychange",this._onVisibilityChange),window.removeEventListener("beforeunload",this._onBeforeUnload))}};var C="exposure_dedup";var V=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(C)}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(C)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(C,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(C);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(C);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var D="stable_id",Qe="traffical_sid";var F=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??Qe}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(D);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(D,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(D),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(D)!==null||this._getCookie()!==null}_persist(e){this._storage.set(D,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 k="traffical:",G=class{constructor(){this._available=this._checkAvailability()}get(e){if(!this._available)return null;try{let t=localStorage.getItem(k+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(k+e,JSON.stringify(i))}catch{}}remove(e){if(this._available)try{localStorage.removeItem(k+e)}catch{}}clear(){if(this._available)try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n?.startsWith(k)&&e.push(n)}e.forEach(t=>localStorage.removeItem(t))}catch{}}_checkAvailability(){try{let e=k+"__test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}},J=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 ie(){let r=new G;return r.get("__check__")!==null||et()?r:new J}function et(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var tt="js-client",nt="0.1.0";function Y(r,e){let t=new v({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=v.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:tt,sdkVersion:nt};e.log(s)},onDestroy(){t.clear()}}}var j=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(){for(let{plugin:e}of this._plugins)if(e.onInitialize)try{await e.onInitialize()}catch(t){console.warn(`[Traffical] Plugin "${e.name}" onInitialize error:`,t)}}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=[]}};var oe="js-client",se="0.1.0",rt="https://sdk.traffical.io",it=6e4,ot=3e5,st=100,T=class{constructor(e){this._state={bundle:null,etag:null,lastFetchTime:0,lastOfflineWarning:0,refreshTimer:null,isInitialized:!1};this._decisionCache=new Map;if(this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??rt,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??it},this._errorBoundary=new N(e.errorBoundary),this._storage=e.storage??ie(),this._eventLogger=new K({endpoint:`${this._options.baseUrl}/v1/events/batch`,apiKey:e.apiKey,storage:this._storage,batchSize:e.eventBatchSize,flushIntervalMs:e.eventFlushIntervalMs,onError:t=>{console.warn("[Traffical] Event logging error:",t.message)}}),this._exposureDedup=new V({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new F({storage:this._storage}),this._plugins=new j,e.trackDecisions!==!1&&this._plugins.register({plugin:Y({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:t=>this._eventLogger.log(t)}),priority:100}),e.plugins)for(let t of e.plugins)this._plugins.register(t);this._options.localConfig&&(this._state.bundle=this._options.localConfig,this._plugins.runConfigUpdate(this._options.localConfig))}async initialize(){await this._errorBoundary.captureAsync("initialize",async()=>{await this._fetchConfig(),this._startBackgroundRefresh(),this._state.isInitialized=!0,await this._plugins.runInitialize()},void 0)}get isInitialized(){return this._state.isInitialized}destroy(){this._state.refreshTimer&&(clearInterval(this._state.refreshTimer),this._state.refreshTimer=null),this._eventLogger.flushBeacon(),this._eventLogger.destroy(),this._plugins.runDestroy()}async refreshConfig(){await this._errorBoundary.swallow("refreshConfig",async()=>{await this._fetchConfig()})}getConfigVersion(){return this._state.bundle?.version??null}getParams(e){return this._errorBoundary.capture("getParams",()=>{let t=this._getEffectiveBundle(),n=this._enrichContext(e.context),i=M(t,n,e.defaults);return this._plugins.runResolve(i),i},e.defaults)}decide(e){return this._errorBoundary.capture("decide",()=>{let t=this._getEffectiveBundle(),n=this._enrichContext(e.context);n=this._plugins.runBeforeDecision(n);let i=O(t,n,e.defaults);return this._cacheDecision(i),this._plugins.runDecision(i),i},{decisionId:I(),assignments:e.defaults,metadata:{timestamp:new Date().toISOString(),unitKeyValue:"",layers:[]}})}trackExposure(e){this._errorBoundary.capture("trackExposure",()=>{let t=e.metadata.unitKeyValue;if(t)for(let n of e.metadata.layers){if(!n.policyId||!n.allocationName||!this._exposureDedup.checkAndMark(t,n.policyId,n.allocationName))continue;let o={type:"exposure",id:W(),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:oe,sdkVersion:se};this._plugins.runExposure(o)&&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,f=n?.decisionId;if(f){let g=this._decisionCache.get(f);g&&(s=g.metadata.layers.filter(u=>u.policyId&&u.allocationName).map(u=>({layerId:u.layerId,policyId:u.policyId,allocationName:u.allocationName})))}let h={type:"track",id:H(),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:f,attribution:s,sdkName:oe,sdkVersion:se};this._plugins.runTrack(h)&&this._eventLogger.log(h)},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)}_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");this._state.bundle=i,this._state.etag=o,this._state.lastFetchTime=Date.now(),this._plugins.runConfigUpdate(i)}catch(n){this._logOfflineWarning(n)}}_startBackgroundRefresh(){this._options.refreshIntervalMs<=0||(this._state.refreshTimer=setInterval(()=>{this._fetchConfig().catch(()=>{})},this._options.refreshIntervalMs))}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>ot&&(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>=st){let t=this._decisionCache.keys().next().value;t&&this._decisionCache.delete(t)}this._decisionCache.set(e.decisionId,e)}};async function ae(r){let e=new T(r);return await e.initialize(),e}function le(r){return new T(r)}function ue(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(a,c){try{return new RegExp(a).test(c)}catch{return c===a}}function f(a,c,l){if(c==="innerHTML")a.innerHTML=l;else if(c==="textContent")a.textContent=l;else if(c==="src"&&"src"in a)a.src=l;else if(c==="href"&&"href"in a)a.href=l;else if(c.startsWith("style.")){let d=c.slice(6);a.style[d]=l}else a.setAttribute(c,l)}function h(a,c){let l=String(c);try{let d=document.querySelectorAll(a.selector);for(let m of d)f(m,a.property,l)}catch(d){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${a.parameterKey}:`,d)}}function g(a,c=!1){n=a;let l=typeof window<"u"?window.location.pathname:"";for(let d of t){if(!c&&!s(d.urlPattern,l))continue;let m=a[d.parameterKey];m!==void 0&&h(d,m)}}function u(){o&&clearTimeout(o),o=setTimeout(()=>{g(n)},e.debounceMs)}function _(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{u()}),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&&_()},onConfigUpdate(a){t=a.domBindings??[]},onResolve(a){g(a)},onDecision(a){g(a.assignments)},onDestroy(){y(),t=[],n={}},applyBindings(a){g(a||n)},getBindings(){return t}}}var p=null;async function at(r){return p?(console.warn("[Traffical] Client already initialized. Returning existing instance."),p):(p=await ae(r),p)}function lt(r){return p?(console.warn("[Traffical] Client already initialized. Returning existing instance."),p):(p=le(r),p.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),p)}function ut(){return p}function ct(){p&&(p.destroy(),p=null)}return ye(dt);})();
|
|
3
3
|
//# sourceMappingURL=traffical.min.js.map
|