@traffical/js-client 0.12.0 → 0.13.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.
- package/dist/client.d.ts +14 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +24 -9
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/warehouse-native-logger.d.ts +74 -18
- package/dist/plugins/warehouse-native-logger.d.ts.map +1 -1
- package/dist/plugins/warehouse-native-logger.js +151 -28
- package/dist/plugins/warehouse-native-logger.js.map +1 -1
- package/dist/traffical.min.js +2 -2
- package/dist/traffical.min.js.map +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
|
@@ -1,13 +1,158 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Warehouse-native
|
|
2
|
+
* Warehouse-native logger factory.
|
|
3
3
|
*
|
|
4
|
-
* Convenience
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Convenience helpers that route Traffical data to a customer-managed
|
|
5
|
+
* pipeline. Two flavours:
|
|
6
|
+
*
|
|
7
|
+
* - `assignmentLogger`: structured AssignmentLogEntry rows (decide/expose).
|
|
8
|
+
* - `eventLogger`: full SDK events (exposure / track / decision).
|
|
9
|
+
*
|
|
10
|
+
* Supported destinations: Segment, Rudderstack, Jitsu (HTTP), or a custom
|
|
11
|
+
* handler. Use `createWarehouseNativeLogger(...)` to get both loggers, or the
|
|
12
|
+
* back-compat `createWarehouseNativeLoggerPlugin(...)` for just the
|
|
13
|
+
* assignment logger.
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_ASSIGNMENT_EVENT_NAME = "Experiment Assignment";
|
|
16
|
+
/** Flattens an AssignmentLogEntry to the snake_case shape used by warehouse syncs. */
|
|
17
|
+
function toAssignmentProps(entry) {
|
|
18
|
+
return {
|
|
19
|
+
unit_key: entry.unitKey,
|
|
20
|
+
policy_id: entry.policyId,
|
|
21
|
+
allocation_name: entry.allocationName,
|
|
22
|
+
timestamp: entry.timestamp,
|
|
23
|
+
layer_id: entry.layerId,
|
|
24
|
+
allocation_id: entry.allocationId,
|
|
25
|
+
org_id: entry.orgId,
|
|
26
|
+
project_id: entry.projectId,
|
|
27
|
+
env: entry.env,
|
|
28
|
+
type: entry.type,
|
|
29
|
+
decision_id: entry.decisionId,
|
|
30
|
+
anonymous_id: entry.anonymousId,
|
|
31
|
+
assignment_id: entry.id,
|
|
32
|
+
...entry.properties,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Default destination event name for a full event. */
|
|
36
|
+
function defaultEventName(event) {
|
|
37
|
+
switch (event.type) {
|
|
38
|
+
case "exposure":
|
|
39
|
+
return "Experiment Exposure";
|
|
40
|
+
case "decision":
|
|
41
|
+
return "Experiment Decision";
|
|
42
|
+
case "track":
|
|
43
|
+
default:
|
|
44
|
+
return event.event;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Flattens a full event to a properties object suitable for analytics/Jitsu. */
|
|
48
|
+
function toEventProps(event) {
|
|
49
|
+
const common = {
|
|
50
|
+
unit_key: event.unitKey,
|
|
51
|
+
org_id: event.orgId,
|
|
52
|
+
project_id: event.projectId,
|
|
53
|
+
env: event.env,
|
|
54
|
+
type: event.type,
|
|
55
|
+
event_id: event.id,
|
|
56
|
+
};
|
|
57
|
+
if (event.type === "track") {
|
|
58
|
+
return {
|
|
59
|
+
...common,
|
|
60
|
+
decision_id: event.decisionId,
|
|
61
|
+
value: event.value,
|
|
62
|
+
...event.properties,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// exposure | decision
|
|
66
|
+
return {
|
|
67
|
+
...common,
|
|
68
|
+
decision_id: event.type === "exposure" ? event.decisionId : event.id,
|
|
69
|
+
assignments: event.assignments,
|
|
70
|
+
...(event.context ?? {}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Builds a Jitsu/Segment envelope for a track-style payload. */
|
|
74
|
+
function jitsuEnvelope(eventName, identity, properties) {
|
|
75
|
+
return {
|
|
76
|
+
type: "track",
|
|
77
|
+
event: eventName,
|
|
78
|
+
userId: identity.unitKey,
|
|
79
|
+
anonymousId: identity.anonymousId,
|
|
80
|
+
messageId: identity.messageId,
|
|
81
|
+
timestamp: identity.timestamp ?? new Date().toISOString(),
|
|
82
|
+
properties,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Creates a sender that POSTs Segment-compatible payloads to Jitsu. */
|
|
86
|
+
function createJitsuSender(dest) {
|
|
87
|
+
const fetchImpl = dest.fetchImpl ?? globalThis.fetch;
|
|
88
|
+
const typePath = dest.eventTypePath ?? "track";
|
|
89
|
+
const buildUrl = dest.endpoint
|
|
90
|
+
? dest.endpoint
|
|
91
|
+
: (type) => `${dest.host.replace(/\/$/, "")}/api/s/${dest.mode === "s2s" ? "s2s/" : ""}${type}`;
|
|
92
|
+
const url = buildUrl(typePath);
|
|
93
|
+
return (body) => {
|
|
94
|
+
if (!fetchImpl)
|
|
95
|
+
return;
|
|
96
|
+
const headers = { "Content-Type": "application/json" };
|
|
97
|
+
if (dest.writeKey)
|
|
98
|
+
headers["X-Write-Key"] = dest.writeKey;
|
|
99
|
+
try {
|
|
100
|
+
void fetchImpl(url, {
|
|
101
|
+
method: "POST",
|
|
102
|
+
headers,
|
|
103
|
+
body: JSON.stringify(body),
|
|
104
|
+
// Best-effort delivery on page unload in browsers.
|
|
105
|
+
keepalive: true,
|
|
106
|
+
}).catch(() => {
|
|
107
|
+
// Swallow network errors — BYO delivery is best-effort.
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Swallow synchronous errors (e.g. fetch unavailable).
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Creates both an `assignmentLogger` and an `eventLogger` for the configured
|
|
117
|
+
* destination. Pass either (or both) to the TrafficalClient options.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* const { assignmentLogger, eventLogger } = createWarehouseNativeLogger({
|
|
122
|
+
* destination: { type: "jitsu", host: "/api/jitsu", mode: "s2s" },
|
|
123
|
+
* });
|
|
124
|
+
* ```
|
|
7
125
|
*/
|
|
126
|
+
export function createWarehouseNativeLogger(options) {
|
|
127
|
+
const dest = options.destination;
|
|
128
|
+
const assignmentEventName = options.eventName ?? DEFAULT_ASSIGNMENT_EVENT_NAME;
|
|
129
|
+
const nameFor = options.eventNameFor ?? defaultEventName;
|
|
130
|
+
if (dest.type === "custom") {
|
|
131
|
+
const assignmentHandler = dest.assignmentHandler ?? dest.handler;
|
|
132
|
+
return {
|
|
133
|
+
assignmentLogger: (entry) => assignmentHandler?.(entry),
|
|
134
|
+
eventLogger: (event) => dest.eventHandler?.(event),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (dest.type === "jitsu") {
|
|
138
|
+
const send = createJitsuSender(dest);
|
|
139
|
+
return {
|
|
140
|
+
assignmentLogger: (entry) => send(jitsuEnvelope(assignmentEventName, { unitKey: entry.unitKey, anonymousId: entry.anonymousId, messageId: entry.id, timestamp: entry.timestamp }, toAssignmentProps(entry))),
|
|
141
|
+
eventLogger: (event) => send(jitsuEnvelope(nameFor(event), { unitKey: event.unitKey, messageId: event.id, timestamp: event.timestamp }, toEventProps(event))),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// segment | rudderstack
|
|
145
|
+
const analytics = dest.analytics;
|
|
146
|
+
return {
|
|
147
|
+
assignmentLogger: (entry) => analytics.track(assignmentEventName, toAssignmentProps(entry)),
|
|
148
|
+
eventLogger: (event) => analytics.track(nameFor(event), toEventProps(event)),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
8
151
|
/**
|
|
9
152
|
* Creates an AssignmentLogger that routes structured assignment entries
|
|
10
|
-
* to Segment, Rudderstack, or a custom handler.
|
|
153
|
+
* to Segment, Rudderstack, Jitsu, or a custom handler.
|
|
154
|
+
*
|
|
155
|
+
* Back-compat wrapper around {@link createWarehouseNativeLogger}.
|
|
11
156
|
*
|
|
12
157
|
* @example
|
|
13
158
|
* ```ts
|
|
@@ -22,28 +167,6 @@
|
|
|
22
167
|
* ```
|
|
23
168
|
*/
|
|
24
169
|
export function createWarehouseNativeLoggerPlugin(options) {
|
|
25
|
-
|
|
26
|
-
return options.destination.handler;
|
|
27
|
-
}
|
|
28
|
-
const eventName = options.eventName ?? "Experiment Assignment";
|
|
29
|
-
const analytics = options.destination.analytics;
|
|
30
|
-
return (entry) => {
|
|
31
|
-
analytics.track(eventName, {
|
|
32
|
-
unit_key: entry.unitKey,
|
|
33
|
-
policy_id: entry.policyId,
|
|
34
|
-
allocation_name: entry.allocationName,
|
|
35
|
-
timestamp: entry.timestamp,
|
|
36
|
-
layer_id: entry.layerId,
|
|
37
|
-
allocation_id: entry.allocationId,
|
|
38
|
-
org_id: entry.orgId,
|
|
39
|
-
project_id: entry.projectId,
|
|
40
|
-
env: entry.env,
|
|
41
|
-
type: entry.type,
|
|
42
|
-
decision_id: entry.decisionId,
|
|
43
|
-
anonymous_id: entry.anonymousId,
|
|
44
|
-
assignment_id: entry.id,
|
|
45
|
-
...entry.properties,
|
|
46
|
-
});
|
|
47
|
-
};
|
|
170
|
+
return createWarehouseNativeLogger(options).assignmentLogger;
|
|
48
171
|
}
|
|
49
172
|
//# sourceMappingURL=warehouse-native-logger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warehouse-native-logger.js","sourceRoot":"","sources":["../../src/plugins/warehouse-native-logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"warehouse-native-logger.js","sourceRoot":"","sources":["../../src/plugins/warehouse-native-logger.ts"],"names":[],"mappings":"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"}
|
package/dist/traffical.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/* @traffical/js-client v0.
|
|
2
|
-
"use strict";var Traffical=(()=>{var V=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var De=Object.getOwnPropertyNames;var Ae=Object.prototype.hasOwnProperty;var Re=(r,e,t)=>e in r?V(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var Oe=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Me=(r,e)=>{for(var t in e)V(r,t,{get:e[t],enumerable:!0})},Le=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of De(e))!Ae.call(r,i)&&i!==t&&V(r,i,{get:()=>e[i],enumerable:!(n=Pe(e,i))||n.enumerable});return r};var Ne=r=>Le(V({},"__esModule",{value:!0}),r);var T=(r,e,t)=>(Re(r,typeof e!="symbol"?e+"":e,t),t);var ve=Oe(()=>{});var Kt={};Me(Kt,{TrafficalClient:()=>P,createDOMBindingPlugin:()=>we,createDebugPlugin:()=>pe,createRedirectAttributionPlugin:()=>ge,createRedirectPlugin:()=>fe,destroy:()=>Bt,init:()=>Mt,initSync:()=>Lt,instance:()=>Nt});var Be=new TextEncoder;function S(r){let e=2166136261,t=Be.encode(r);for(let n=0;n<t.length;n++)e^=t[n],e=Math.imul(e,16777619);return e>>>0}function F(r,e,t){let n=`${r}:${e}`;return S(n)%t}function Q(r,e){return r>=e[0]&&r<=e[1]}function $(r,e){for(let t of e)if(Q(r,t.bucketRange))return t;return null}function w(r,e){if(r.length===0||r.length===1)return 0;let n=S(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 ee(r,e){let{field:t,op:n,value:i,values:o}=r,s=Fe(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 U(r,e){return r.length===0?!0:r.every(t=>ee(t,e))}function Fe(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 te(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 ne(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,u)=>a+u,0);return o.map(a=>a/s)}function ie(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,u)=>a+u,0);return s===0?Array(t).fill(1/t):o.map(a=>a/s)}function j(r,e,t){let n=r.contextualModel;if(!n||r.allocations.length===0)return null;let i=$e(n,r.allocations,e),o=ne(i,n.gamma),s=ie(o,n.actionProbabilityFloor),a=`ctx:${t}:${r.id}`,u=w(s,a);return r.allocations[u]}function $e(r,e,t){return e.map(n=>{let i=r.coefficients[n.name];return i?te(i,t):r.defaultAllocationScore})}var Ue=r=>crypto.getRandomValues(new Uint8Array(r)),je=(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),u=i|0;for(;u--;)if(s+=r[a[u]&n]||"",s.length>=o)return s}}},me=(r,e=21)=>je(r,e|0,Ue);function W(r){let e=new Error(r);return e.source="ulid",e}var re="0123456789ABCDEFGHJKMNPQRSTVWXYZ",D=re.length,ye=Math.pow(2,48)-1,We=10,ze=16;function He(r){let e=Math.floor(r()*D);return e===D&&(e=D-1),re.charAt(e)}function Ge(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>ye)throw W("cannot encode time greater than "+ye);if(r<0)throw W("time must be positive");if(Number.isInteger(Number(r))===!1)throw W("time must be an integer");let t,n="";for(;e>0;e--)t=r%D,n=re.charAt(t)+n,r=(r-t)/D;return n}function qe(r,e){let t="";for(;r>0;r--)t=He(e)+t;return t}function Xe(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=ve();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 W("secure crypto unusable, insecure Math.random not allowed")}function Je(r){return r||(r=Xe()),function(t){return isNaN(t)&&(t=Date.now()),Ge(t,We)+qe(ze,r)}}var _e=Je();var Ye="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Ze=8,on=me(Ye,Ze);function A(r){return`${r}_${_e()}`}function R(){return A("dec")}function oe(){return A("exp")}function se(){return A("trk")}function ae(){return A("asn")}function Qe(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 et(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 be(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function tt(r,e,t,n){let i=r.entityState?.[e];if(!i)return be(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:be(n)}function nt(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=et(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let g=i.dynamicAllocations.countKey,b=t[g];if(typeof b!="number"||b<=0)return null;a=Math.floor(b),s=Array.from({length:a},(c,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 u=tt(r,e.id,o,a),p=`${o}:${n}:${e.id}`,y=w(u,p);return{allocation:s[y],entityId:o}}function O(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function Ie(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=O(r,e)??"",u=new Set(Object.keys(t)),p=r.parameters.filter(g=>u.has(g.key));for(let g of p)g.key in i&&(i[g.key]=g.default);let y=new Map;for(let g of p){let b=y.get(g.layerId)||[];b.push(g),y.set(g.layerId,b)}for(let g of r.layers){let b=y.get(g.id),c=b&&b.length>0,f=g.unitKey,h=f?String(e[f]??""):a;if(!h){o.push({layerId:g.id,bucket:-1,...f?{unitKey:f,unitKeyValue:""}:{},...c?{}:{attributionOnly:!0}});continue}let m=F(h,g.id,r.hashing.bucketCount),E,l;for(let d of g.policies)if(d.state==="running"){if(d.eligibleBucketRange){let{start:v,end:_}=d.eligibleBucketRange;if(m<v||m>_)continue}if(U(d.conditions,e)){if(d.contextualModel){let v=j(d,e,h);if(v){if(E=d,l=v,s.push(d),c)for(let[_,k]of Object.entries(v.overrides))_ in i&&(i[_]=k);break}}if(d.entityConfig&&d.entityConfig.resolutionMode==="bundle"){let v=nt(r,d,e,h);if(v){if(E=d,l=v.allocation,s.push(d),c&&!d.entityConfig.dynamicAllocations)for(let[_,k]of Object.entries(v.allocation.overrides))_ in i&&(i[_]=k);break}}else if(d.entityConfig&&d.entityConfig.resolutionMode==="edge"){let v=n?.edgeResults?.get(d.id);if(v){if(E=d,s.push(d),d.entityConfig.dynamicAllocations)l={id:`${d.id}_dynamic_${v.allocationIndex}`,name:String(v.allocationIndex),bucketRange:[0,0],overrides:{}};else if(d.allocations[v.allocationIndex]&&(l=d.allocations[v.allocationIndex],c&&l))for(let[_,k]of Object.entries(l.overrides))_ in i&&(i[_]=k);break}continue}else{let v=$(m,d.allocations);if(v){if(E=d,l=v,s.push(d),c)for(let[_,k]of Object.entries(v.overrides))_ in i&&(i[_]=k);break}}}}o.push({layerId:g.id,bucket:m,policyId:E?.id,policyKey:E?.key,allocationId:l?.id,allocationName:l?.name,allocationKey:l?.key,...f?{unitKey:f,unitKeyValue:h}:{},...c?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function z(r,e,t,n){return Ie(r,e,t,n).assignments}function H(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=Ie(r,e,t,n),u=Qe(e,a);return{decisionId:R(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:u}}}var C=class r{constructor(e={}){T(this,"_seen",new Map);T(this,"_ttlMs");T(this,"_maxEntries");T(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 M=class{constructor(e){T(this,"config");T(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 le(r,e,t,n,i){let o=[];for(let a of e){let u=t[a];if(u==null)return null;o.push(String(u))}let s=o.join("_");return{policyId:r,entityId:s,unitKeyValue:n,allocationCount:i,context:t}}var G=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 q="failed_events";var X=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._onSchemaWarnings=e.onSchemaWarnings,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}`);if(this._onSchemaWarnings)try{let n=await t.json();n.schemaWarnings&&n.schemaWarnings.length>0&&this._onSchemaWarnings(n.schemaWarnings)}catch{}}_persistFailedEvents(e){let n=[...this._storage.get(q)??[],...e].slice(-100);this._storage.set(q,n)}_retryFailedEvents(){let e=this._storage.get(q);!e||e.length===0||(this._storage.remove(q),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 L="exposure_dedup";var N=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(L)}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(L)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(L,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(L);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(L);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var B="stable_id",vt="traffical_sid";var J=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??vt}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(B);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(B,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(B),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(B)!==null||this._getCookie()!==null}_persist(e){this._storage.set(B,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:",ce=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}}},ue=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 Ee(){let r=new ce;return r.get("__check__")!==null||yt()?r:new ue}function yt(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var x="0.12.0";var _t="js-client";function de(r,e){let t=new C({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=C.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:_t,sdkVersion:x};e.log(s)},onDestroy(){t.clear()}}}var bt="traffical_rdr";function It(r,e,t){if(!(typeof document>"u"))try{document.cookie=`${r}=${encodeURIComponent(e)}; max-age=${t}; path=/; SameSite=Lax`}catch{}}function fe(r={}){let e=r.parameterKey??"redirect.url",t=r.compareMode??"pathname",n=r.cookieName??bt;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(u=>u.policyId&&u.allocationName);a&&It(n,JSON.stringify({l:a.layerId,p:a.policyId,a:a.allocationName,ts:Date.now()}),86400),window.location.replace(o)}}}var Et="traffical_rdr";function Tt(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 xt(r,e){let t=Tt(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 ge(r={}){let e=r.cookieName??Et,t=r.expiryMs??864e5;function n(i){let o=xt(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 Y=[],Te={};function kt(){if(typeof window>"u")return{version:1,instances:Te,subscribe:()=>()=>{}};if(!window.__TRAFFICAL_DEBUG__){let r={version:1,instances:Te,subscribe(e){return Y.push(e),()=>{Y=Y.filter(t=>t!==e)}}};window.__TRAFFICAL_DEBUG__=r}return window.__TRAFFICAL_DEBUG__}function xe(r){for(let e of Y)try{e(r)}catch{}}var Ct=0;function St(){return`traffical_${Date.now().toString(36)}_${(++Ct).toString(36)}`}function wt(){return`evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}var Pt="traffical-debug";function pe(r={}){let e=r.instanceId??St(),t=r.maxEvents??500,n=null,i=null,o={},s=[],a=null,u=null,p=[],y=[],g=[];function b(){return{ready:n?.isInitialized===!0,stableId:n?.getStableId?.()??null,effectiveUnitKey:u,configVersion:n?.getConfigVersion?.()??null,assignments:{...o},layers:[...s],lastDecisionId:a,overrides:n?.getOverrides?.()??{}}}function c(){let l=b();for(let d of y)try{d(l)}catch{}}function f(l,d){let v={id:wt(),type:l,timestamp:Date.now(),data:d};p.push(v),p.length>t&&p.splice(0,p.length-t);for(let _ of g)try{_(v)}catch{}}function h(){if(n)try{n.decide({context:{},defaults:{}})}catch{}}let m={id:e,meta:{orgId:"",projectId:"",env:"",sdkVersion:x},getState:b,subscribe(l){return y.push(l),()=>{y=y.filter(d=>d!==l)}},getEvents(l){return l!==void 0?p.slice(-l):[...p]},onEvent(l){return g.push(l),()=>{g=g.filter(d=>d!==l)}},getConfigBundle(){return i},setUnitKey(l){n?.identify?n.identify(l):n?.setStableId&&n.setStableId(l),c()},setOverride(l,d){n?.applyOverrides&&n.applyOverrides({[l]:d}),c(),h()},clearOverride(l){if(n?.getOverrides&&n?.applyOverrides){let d=n.getOverrides();delete d[l],n.clearOverrides?.(),n.applyOverrides(d)}c(),h()},clearAllOverrides(){n?.clearOverrides?.(),c(),h()},getOverrides(){return n?.getOverrides?.()??{}},reDecide(){h()},async refresh(){n?.refreshConfig&&await n.refreshConfig()}};return{name:Pt,onInitialize(l){n=l,i&&(m.meta.orgId=i.orgId,m.meta.projectId=i.projectId,m.meta.env=i.env);let d=kt();d.instances[e]=m,xe({type:"register",instanceId:e}),c()},onConfigUpdate(l){i=l,m.meta.orgId=l.orgId,m.meta.projectId=l.projectId,m.meta.env=l.env,c()},onDecision(l){o={...l.assignments},s=l.metadata?.layers?[...l.metadata.layers]:[],a=l.decisionId,l.metadata?.unitKeyValue&&(u=l.metadata.unitKeyValue),f("decision",l),c()},onResolve(l){o={...l},c()},onExposure(l){return f("exposure",l),!0},onTrack(l){return f("track",l),!0},onDestroy(){let l=typeof window<"u"?window.__TRAFFICAL_DEBUG__:null;l&&(delete l.instances[e],xe({type:"unregister",instanceId:e})),y=[],g=[],n=null}}}var Z=class{constructor(){this._plugins=[]}register(e){let t="plugin"in e?e.plugin:e,n="priority"in e?e.priority??0:0;return this._plugins.some(i=>i.plugin.name===t.name)?(console.warn(`[Traffical] Plugin "${t.name}" already registered, skipping.`),!1):(this._plugins.push({plugin:t,priority:n}),this._plugins.sort((i,o)=>o.priority-i.priority),!0)}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 ke(){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 he="js-client",Dt="https://sdk.traffical.io",At=6e4,Rt=3e5,Ot=100,P=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;this._identityListeners=[];this._overrideListeners=[];this._overrides={};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??At,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 M(n),this._errorBoundary=new G(e.errorBoundary),this._storage=e.storage??Ee(),this._lifecycleProvider=e.lifecycleProvider??ke(),!e.onSchemaWarnings)try{typeof globalThis<"u"&&globalThis.process?.env?.NODE_ENV==="development"&&(e.onSchemaWarnings=o=>{for(let s of o)console.warn(`[Traffical] Schema warning for "${s.event}":`,s.violations.map(a=>`${a.path}: ${a.message}`).join(", "))})}catch{}if(this._eventLogger=new X({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)},onSchemaWarnings:e.onSchemaWarnings}),this._exposureDedup=new N({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new J({storage:this._storage}),this._plugins=new Z,this._assignmentLogger=e.assignmentLogger,this._disableCloudEvents=e.disableCloudEvents??!1,this._assignmentLoggerDedup=e.deduplicateAssignmentLogger!==!1&&e.assignmentLogger?new N({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}):null,e.trackDecisions!==!1&&!this._disableCloudEvents&&this._plugins.register({plugin:de({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);if(this._options.localConfig&&(this._state.bundle=this._options.localConfig,this._plugins.runConfigUpdate(this._options.localConfig)),typeof window<"u"){let i=window;i.__TRAFFICAL_INSTANCES__??(i.__TRAFFICAL_INSTANCES__=[]),i.__TRAFFICAL_INSTANCES__.push(this)}}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(){if(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(),this._identityListeners=[],this._overrideListeners=[],this._overrides={},typeof window<"u"){let t=window.__TRAFFICAL_INSTANCES__;if(t){let n=t.indexOf(this);n!==-1&&t.splice(n,1)}}}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),this._applyOverridesToResult(o),o}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context),i=z(t,n,e.defaults);return this._plugins.runResolve(i),this._applyOverridesToResult(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[p,y]of Object.entries(s.assignments))p in a&&(a[p]=y);let u={decisionId:s.decisionId,assignments:a,metadata:s.metadata};return this._cacheDecision(u),this._updateCumulativeAttribution(u),this._plugins.runDecision(u),this._applyOverridesToResult(u.assignments),this._emitAssignmentLogEntries(u,"decision"),u}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context);n=this._plugins.runBeforeDecision(n);let i=this._state.cachedEdgeResults??void 0,o=H(t,n,e.defaults,i);return this._cacheDecision(o),this._updateCumulativeAttribution(o),this._plugins.runDecision(o),this._applyOverridesToResult(o.assignments),this._emitAssignmentLogEntries(o,"decision"),o},{decisionId:R(),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,"exposure");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:oe(),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:he,sdkVersion:x};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,u={type:"track",id:se(),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:he,sdkVersion:x};this._plugins.runTrack(u)&&(this._disableCloudEvents||this._eventLogger.log(u))},void 0)}async flushEvents(){await this._errorBoundary.swallow("flushEvents",async()=>{await this._eventLogger.flush()})}use(e){if(!this._plugins.register(e))return this;if(this._state.isInitialized){try{e.onInitialize?.(this)}catch(n){console.warn(`[Traffical] Plugin "${e.name}" late onInitialize error:`,n)}if(this._state.bundle)try{e.onConfigUpdate?.(this._state.bundle)}catch(n){console.warn(`[Traffical] Plugin "${e.name}" late onConfigUpdate error:`,n)}}return this}getPlugin(e){return this._plugins.get(e)}getStableId(){return this._stableId.getId()}setStableId(e){this._stableId.setId(e)}identify(e){this._stableId.setId(e);for(let t of this._identityListeners)try{t(e)}catch{}}onIdentityChange(e){return this._identityListeners.push(e),()=>{this._identityListeners=this._identityListeners.filter(t=>t!==e)}}onOverridesChange(e){return this._overrideListeners.push(e),()=>{this._overrideListeners=this._overrideListeners.filter(t=>t!==e)}}applyOverrides(e){Object.assign(this._overrides,e),this._notifyOverrideListeners()}clearOverrides(){this._overrides={},this._notifyOverrideListeners()}getOverrides(){return{...this._overrides}}_notifyOverrideListeners(){let e={...this._overrides};for(let t of this._overrideListeners)try{t(e)}catch{}}_emitAssignmentLogEntries(e,t){if(!this._assignmentLogger)return;let n=e.metadata.unitKeyValue;if(n)for(let i of e.metadata.layers)!i.policyId||!i.allocationName||this._assignmentLoggerDedup&&!this._assignmentLoggerDedup.checkAndMark(n,i.policyId,`${i.allocationName}:${t}`)||this._assignmentLogger({unitKey:n,policyId:i.policyId,policyKey:i.policyKey,allocationName:i.allocationName,allocationKey:i.allocationKey,timestamp:e.metadata.timestamp,layerId:i.layerId,allocationId:i.allocationId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,sdkName:he,sdkVersion:x,properties:e.metadata.filteredContext,type:t,decisionId:e.decisionId,anonymousId:this._stableId.getId(),id:ae()})}_applyOverridesToResult(e){let t=Object.keys(this._overrides);if(t.length!==0)for(let n of t)n in e&&(e[n]=this._overrides[n])}_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=O(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 le(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 u=0;u<o.length;u++){let p=s[u];p&&a.set(o[u].policyId,{allocationIndex:p.allocationIndex,entityId:o[u].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>Rt&&(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>=Ot){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 Ce(r){let e=new P(r);return await e.initialize(),e}function Se(r){return new P(r)}function we(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(c,f){try{return new RegExp(c).test(f)}catch{return f===c}}function a(c,f,h){if(f==="innerHTML")c.innerHTML=h;else if(f==="textContent")c.textContent=h;else if(f==="src"&&"src"in c)c.src=h;else if(f==="href"&&"href"in c)c.href=h;else if(f.startsWith("style.")){let m=f.slice(6);c.style[m]=h}else c.setAttribute(f,h)}function u(c,f){let h=String(f);try{let m=document.querySelectorAll(c.selector);for(let E of m)a(E,c.property,h)}catch(m){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${c.parameterKey}:`,m)}}function p(c,f=!1){n=c;let h=typeof window<"u"?window.location.pathname:"";for(let m of t){if(!f&&!s(m.urlPattern,h))continue;let E=c[m.parameterKey];E!==void 0&&u(m,E)}}function y(){o&&clearTimeout(o),o=setTimeout(()=>{p(n)},e.debounceMs)}function g(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{y()}),i.observe(document.body,{childList:!0,subtree:!0}))}function b(){i&&(i.disconnect(),i=null),o&&(clearTimeout(o),o=null)}return{name:"dom-binding",onInitialize(){e.observeMutations&&g()},onConfigUpdate(c){t=c.domBindings??[]},onResolve(c){p(c)},onDecision(c){p(c.assignments)},onDestroy(){b(),t=[],n={}},applyBindings(c){p(c||n)},getBindings(){return t}}}var I=null;async function Mt(r){return I?(console.warn("[Traffical] Client already initialized. Returning existing instance."),I):(I=await Ce(r),I)}function Lt(r){return I?(console.warn("[Traffical] Client already initialized. Returning existing instance."),I):(I=Se(r),I.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),I)}function Nt(){return I}function Bt(){I&&(I.destroy(),I=null)}return Ne(Kt);})();
|
|
1
|
+
/* @traffical/js-client v0.13.0 */
|
|
2
|
+
"use strict";var Traffical=(()=>{var V=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var De=Object.prototype.hasOwnProperty;var Re=(r,e,t)=>e in r?V(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var Oe=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Me=(r,e)=>{for(var t in e)V(r,t,{get:e[t],enumerable:!0})},Le=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ae(e))!De.call(r,i)&&i!==t&&V(r,i,{get:()=>e[i],enumerable:!(n=Pe(e,i))||n.enumerable});return r};var Ne=r=>Le(V({},"__esModule",{value:!0}),r);var T=(r,e,t)=>(Re(r,typeof e!="symbol"?e+"":e,t),t);var ye=Oe(()=>{});var Kt={};Me(Kt,{TrafficalClient:()=>P,createDOMBindingPlugin:()=>Ce,createDebugPlugin:()=>pe,createRedirectAttributionPlugin:()=>ge,createRedirectPlugin:()=>fe,destroy:()=>Bt,init:()=>Mt,initSync:()=>Lt,instance:()=>Nt});var Be=new TextEncoder;function S(r){let e=2166136261,t=Be.encode(r);for(let n=0;n<t.length;n++)e^=t[n],e=Math.imul(e,16777619);return e>>>0}function F(r,e,t){let n=`${r}:${e}`;return S(n)%t}function Q(r,e){return r>=e[0]&&r<=e[1]}function $(r,e){for(let t of e)if(Q(r,t.bucketRange))return t;return null}function C(r,e){if(r.length===0||r.length===1)return 0;let n=S(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 ee(r,e){let{field:t,op:n,value:i,values:o}=r,s=Fe(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 j(r,e){return r.length===0?!0:r.every(t=>ee(t,e))}function Fe(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 te(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 ne(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,u)=>a+u,0);return o.map(a=>a/s)}function ie(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,u)=>a+u,0);return s===0?Array(t).fill(1/t):o.map(a=>a/s)}function U(r,e,t){let n=r.contextualModel;if(!n||r.allocations.length===0)return null;let i=$e(n,r.allocations,e),o=ne(i,n.gamma),s=ie(o,n.actionProbabilityFloor),a=`ctx:${t}:${r.id}`,u=C(s,a);return r.allocations[u]}function $e(r,e,t){return e.map(n=>{let i=r.coefficients[n.name];return i?te(i,t):r.defaultAllocationScore})}var je=r=>crypto.getRandomValues(new Uint8Array(r)),Ue=(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),u=i|0;for(;u--;)if(s+=r[a[u]&n]||"",s.length>=o)return s}}},me=(r,e=21)=>Ue(r,e|0,je);function W(r){let e=new Error(r);return e.source="ulid",e}var re="0123456789ABCDEFGHJKMNPQRSTVWXYZ",A=re.length,ve=Math.pow(2,48)-1,We=10,ze=16;function He(r){let e=Math.floor(r()*A);return e===A&&(e=A-1),re.charAt(e)}function Ge(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>ve)throw W("cannot encode time greater than "+ve);if(r<0)throw W("time must be positive");if(Number.isInteger(Number(r))===!1)throw W("time must be an integer");let t,n="";for(;e>0;e--)t=r%A,n=re.charAt(t)+n,r=(r-t)/A;return n}function Xe(r,e){let t="";for(;r>0;r--)t=He(e)+t;return t}function qe(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=ye();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 W("secure crypto unusable, insecure Math.random not allowed")}function Je(r){return r||(r=qe()),function(t){return isNaN(t)&&(t=Date.now()),Ge(t,We)+Xe(ze,r)}}var _e=Je();var Ye="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Ze=8,on=me(Ye,Ze);function D(r){return`${r}_${_e()}`}function R(){return D("dec")}function oe(){return D("exp")}function se(){return D("trk")}function ae(){return D("asn")}function Qe(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 et(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 be(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function tt(r,e,t,n){let i=r.entityState?.[e];if(!i)return be(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:be(n)}function nt(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=et(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let g=i.dynamicAllocations.countKey,b=t[g];if(typeof b!="number"||b<=0)return null;a=Math.floor(b),s=Array.from({length:a},(c,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 u=tt(r,e.id,o,a),p=`${o}:${n}:${e.id}`,v=C(u,p);return{allocation:s[v],entityId:o}}function O(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function Ie(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=O(r,e)??"",u=new Set(Object.keys(t)),p=r.parameters.filter(g=>u.has(g.key));for(let g of p)g.key in i&&(i[g.key]=g.default);let v=new Map;for(let g of p){let b=v.get(g.layerId)||[];b.push(g),v.set(g.layerId,b)}for(let g of r.layers){let b=v.get(g.id),c=b&&b.length>0,f=g.unitKey,h=f?String(e[f]??""):a;if(!h){o.push({layerId:g.id,bucket:-1,...f?{unitKey:f,unitKeyValue:""}:{},...c?{}:{attributionOnly:!0}});continue}let m=F(h,g.id,r.hashing.bucketCount),E,l;for(let d of g.policies)if(d.state==="running"){if(d.eligibleBucketRange){let{start:y,end:_}=d.eligibleBucketRange;if(m<y||m>_)continue}if(j(d.conditions,e)){if(d.contextualModel){let y=U(d,e,h);if(y){if(E=d,l=y,s.push(d),c)for(let[_,k]of Object.entries(y.overrides))_ in i&&(i[_]=k);break}}if(d.entityConfig&&d.entityConfig.resolutionMode==="bundle"){let y=nt(r,d,e,h);if(y){if(E=d,l=y.allocation,s.push(d),c&&!d.entityConfig.dynamicAllocations)for(let[_,k]of Object.entries(y.allocation.overrides))_ in i&&(i[_]=k);break}}else if(d.entityConfig&&d.entityConfig.resolutionMode==="edge"){let y=n?.edgeResults?.get(d.id);if(y){if(E=d,s.push(d),d.entityConfig.dynamicAllocations)l={id:`${d.id}_dynamic_${y.allocationIndex}`,name:String(y.allocationIndex),bucketRange:[0,0],overrides:{}};else if(d.allocations[y.allocationIndex]&&(l=d.allocations[y.allocationIndex],c&&l))for(let[_,k]of Object.entries(l.overrides))_ in i&&(i[_]=k);break}continue}else{let y=$(m,d.allocations);if(y){if(E=d,l=y,s.push(d),c)for(let[_,k]of Object.entries(y.overrides))_ in i&&(i[_]=k);break}}}}o.push({layerId:g.id,bucket:m,policyId:E?.id,policyKey:E?.key,allocationId:l?.id,allocationName:l?.name,allocationKey:l?.key,...f?{unitKey:f,unitKeyValue:h}:{},...c?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function z(r,e,t,n){return Ie(r,e,t,n).assignments}function H(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=Ie(r,e,t,n),u=Qe(e,a);return{decisionId:R(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:u}}}var w=class r{constructor(e={}){T(this,"_seen",new Map);T(this,"_ttlMs");T(this,"_maxEntries");T(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 M=class{constructor(e){T(this,"config");T(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 le(r,e,t,n,i){let o=[];for(let a of e){let u=t[a];if(u==null)return null;o.push(String(u))}let s=o.join("_");return{policyId:r,entityId:s,unitKeyValue:n,allocationCount:i,context:t}}var G=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 X="failed_events";var q=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._onSchemaWarnings=e.onSchemaWarnings,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}`);if(this._onSchemaWarnings)try{let n=await t.json();n.schemaWarnings&&n.schemaWarnings.length>0&&this._onSchemaWarnings(n.schemaWarnings)}catch{}}_persistFailedEvents(e){let n=[...this._storage.get(X)??[],...e].slice(-100);this._storage.set(X,n)}_retryFailedEvents(){let e=this._storage.get(X);!e||e.length===0||(this._storage.remove(X),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 L="exposure_dedup";var N=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(L)}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(L)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(L,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(L);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(L);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var B="stable_id",yt="traffical_sid";var J=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??yt}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(B);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(B,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(B),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(B)!==null||this._getCookie()!==null}_persist(e){this._storage.set(B,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:",ce=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}}},ue=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 Ee(){let r=new ce;return r.get("__check__")!==null||vt()?r:new ue}function vt(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var x="0.13.0";var _t="js-client";function de(r,e){let t=new w({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=w.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:_t,sdkVersion:x};e.log(s)},onDestroy(){t.clear()}}}var bt="traffical_rdr";function It(r,e,t){if(!(typeof document>"u"))try{document.cookie=`${r}=${encodeURIComponent(e)}; max-age=${t}; path=/; SameSite=Lax`}catch{}}function fe(r={}){let e=r.parameterKey??"redirect.url",t=r.compareMode??"pathname",n=r.cookieName??bt;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(u=>u.policyId&&u.allocationName);a&&It(n,JSON.stringify({l:a.layerId,p:a.policyId,a:a.allocationName,ts:Date.now()}),86400),window.location.replace(o)}}}var Et="traffical_rdr";function Tt(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 xt(r,e){let t=Tt(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 ge(r={}){let e=r.cookieName??Et,t=r.expiryMs??864e5;function n(i){let o=xt(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 Y=[],Te={};function kt(){if(typeof window>"u")return{version:1,instances:Te,subscribe:()=>()=>{}};if(!window.__TRAFFICAL_DEBUG__){let r={version:1,instances:Te,subscribe(e){return Y.push(e),()=>{Y=Y.filter(t=>t!==e)}}};window.__TRAFFICAL_DEBUG__=r}return window.__TRAFFICAL_DEBUG__}function xe(r){for(let e of Y)try{e(r)}catch{}}var wt=0;function St(){return`traffical_${Date.now().toString(36)}_${(++wt).toString(36)}`}function Ct(){return`evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}var Pt="traffical-debug";function pe(r={}){let e=r.instanceId??St(),t=r.maxEvents??500,n=null,i=null,o={},s=[],a=null,u=null,p=[],v=[],g=[];function b(){return{ready:n?.isInitialized===!0,stableId:n?.getStableId?.()??null,effectiveUnitKey:u,configVersion:n?.getConfigVersion?.()??null,assignments:{...o},layers:[...s],lastDecisionId:a,overrides:n?.getOverrides?.()??{}}}function c(){let l=b();for(let d of v)try{d(l)}catch{}}function f(l,d){let y={id:Ct(),type:l,timestamp:Date.now(),data:d};p.push(y),p.length>t&&p.splice(0,p.length-t);for(let _ of g)try{_(y)}catch{}}function h(){if(n)try{n.decide({context:{},defaults:{}})}catch{}}let m={id:e,meta:{orgId:"",projectId:"",env:"",sdkVersion:x},getState:b,subscribe(l){return v.push(l),()=>{v=v.filter(d=>d!==l)}},getEvents(l){return l!==void 0?p.slice(-l):[...p]},onEvent(l){return g.push(l),()=>{g=g.filter(d=>d!==l)}},getConfigBundle(){return i},setUnitKey(l){n?.identify?n.identify(l):n?.setStableId&&n.setStableId(l),c()},setOverride(l,d){n?.applyOverrides&&n.applyOverrides({[l]:d}),c(),h()},clearOverride(l){if(n?.getOverrides&&n?.applyOverrides){let d=n.getOverrides();delete d[l],n.clearOverrides?.(),n.applyOverrides(d)}c(),h()},clearAllOverrides(){n?.clearOverrides?.(),c(),h()},getOverrides(){return n?.getOverrides?.()??{}},reDecide(){h()},async refresh(){n?.refreshConfig&&await n.refreshConfig()}};return{name:Pt,onInitialize(l){n=l,i&&(m.meta.orgId=i.orgId,m.meta.projectId=i.projectId,m.meta.env=i.env);let d=kt();d.instances[e]=m,xe({type:"register",instanceId:e}),c()},onConfigUpdate(l){i=l,m.meta.orgId=l.orgId,m.meta.projectId=l.projectId,m.meta.env=l.env,c()},onDecision(l){o={...l.assignments},s=l.metadata?.layers?[...l.metadata.layers]:[],a=l.decisionId,l.metadata?.unitKeyValue&&(u=l.metadata.unitKeyValue),f("decision",l),c()},onResolve(l){o={...l},c()},onExposure(l){return f("exposure",l),!0},onTrack(l){return f("track",l),!0},onDestroy(){let l=typeof window<"u"?window.__TRAFFICAL_DEBUG__:null;l&&(delete l.instances[e],xe({type:"unregister",instanceId:e})),v=[],g=[],n=null}}}var Z=class{constructor(){this._plugins=[]}register(e){let t="plugin"in e?e.plugin:e,n="priority"in e?e.priority??0:0;return this._plugins.some(i=>i.plugin.name===t.name)?(console.warn(`[Traffical] Plugin "${t.name}" already registered, skipping.`),!1):(this._plugins.push({plugin:t,priority:n}),this._plugins.sort((i,o)=>o.priority-i.priority),!0)}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 ke(){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 he="js-client",At="https://sdk.traffical.io",Dt=6e4,Rt=3e5,Ot=100,P=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;this._identityListeners=[];this._overrideListeners=[];this._overrides={};let t=e.evaluationMode??"bundle";this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??At,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??Dt,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 M(n),this._errorBoundary=new G(e.errorBoundary),this._storage=e.storage??Ee(),this._lifecycleProvider=e.lifecycleProvider??ke(),!e.onSchemaWarnings)try{typeof globalThis<"u"&&globalThis.process?.env?.NODE_ENV==="development"&&(e.onSchemaWarnings=o=>{for(let s of o)console.warn(`[Traffical] Schema warning for "${s.event}":`,s.violations.map(a=>`${a.path}: ${a.message}`).join(", "))})}catch{}if(this._eventLogger=new q({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)},onSchemaWarnings:e.onSchemaWarnings}),this._exposureDedup=new N({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new J({storage:this._storage}),this._plugins=new Z,this._assignmentLogger=e.assignmentLogger,this._byoEventLogger=e.eventLogger,this._disableCloudEvents=e.disableCloudEvents??!1,this._assignmentLoggerDedup=e.deduplicateAssignmentLogger!==!1&&e.assignmentLogger?new N({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}):null,e.trackDecisions!==!1&&(!this._disableCloudEvents||this._byoEventLogger)&&this._plugins.register({plugin:de({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:i=>this._dispatchEvent(i)}),priority:100}),e.plugins)for(let i of e.plugins)this._plugins.register(i);if(this._options.localConfig&&(this._state.bundle=this._options.localConfig,this._plugins.runConfigUpdate(this._options.localConfig)),typeof window<"u"){let i=window;i.__TRAFFICAL_INSTANCES__??(i.__TRAFFICAL_INSTANCES__=[]),i.__TRAFFICAL_INSTANCES__.push(this)}}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(){if(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(),this._identityListeners=[],this._overrideListeners=[],this._overrides={},typeof window<"u"){let t=window.__TRAFFICAL_INSTANCES__;if(t){let n=t.indexOf(this);n!==-1&&t.splice(n,1)}}}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),this._applyOverridesToResult(o),o}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context),i=z(t,n,e.defaults);return this._plugins.runResolve(i),this._applyOverridesToResult(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[p,v]of Object.entries(s.assignments))p in a&&(a[p]=v);let u={decisionId:s.decisionId,assignments:a,metadata:s.metadata};return this._cacheDecision(u),this._updateCumulativeAttribution(u),this._plugins.runDecision(u),this._applyOverridesToResult(u.assignments),this._emitAssignmentLogEntries(u,"decision"),u}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context);n=this._plugins.runBeforeDecision(n);let i=this._state.cachedEdgeResults??void 0,o=H(t,n,e.defaults,i);return this._cacheDecision(o),this._updateCumulativeAttribution(o),this._plugins.runDecision(o),this._applyOverridesToResult(o.assignments),this._emitAssignmentLogEntries(o,"decision"),o},{decisionId:R(),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,"exposure");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:oe(),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:he,sdkVersion:x};this._plugins.runExposure(o)&&this._dispatchEvent(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,u={type:"track",id:se(),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:he,sdkVersion:x};this._plugins.runTrack(u)&&this._dispatchEvent(u)},void 0)}async flushEvents(){await this._errorBoundary.swallow("flushEvents",async()=>{await this._eventLogger.flush()})}use(e){if(!this._plugins.register(e))return this;if(this._state.isInitialized){try{e.onInitialize?.(this)}catch(n){console.warn(`[Traffical] Plugin "${e.name}" late onInitialize error:`,n)}if(this._state.bundle)try{e.onConfigUpdate?.(this._state.bundle)}catch(n){console.warn(`[Traffical] Plugin "${e.name}" late onConfigUpdate error:`,n)}}return this}getPlugin(e){return this._plugins.get(e)}getStableId(){return this._stableId.getId()}setStableId(e){this._stableId.setId(e)}identify(e){this._stableId.setId(e);for(let t of this._identityListeners)try{t(e)}catch{}}onIdentityChange(e){return this._identityListeners.push(e),()=>{this._identityListeners=this._identityListeners.filter(t=>t!==e)}}onOverridesChange(e){return this._overrideListeners.push(e),()=>{this._overrideListeners=this._overrideListeners.filter(t=>t!==e)}}applyOverrides(e){Object.assign(this._overrides,e),this._notifyOverrideListeners()}clearOverrides(){this._overrides={},this._notifyOverrideListeners()}getOverrides(){return{...this._overrides}}_notifyOverrideListeners(){let e={...this._overrides};for(let t of this._overrideListeners)try{t(e)}catch{}}_dispatchEvent(e){if(this._byoEventLogger)try{this._byoEventLogger(e)}catch{}this._disableCloudEvents||this._eventLogger.log(e)}_emitAssignmentLogEntries(e,t){if(!this._assignmentLogger)return;let n=e.metadata.unitKeyValue;if(n)for(let i of e.metadata.layers)!i.policyId||!i.allocationName||this._assignmentLoggerDedup&&!this._assignmentLoggerDedup.checkAndMark(n,i.policyId,`${i.allocationName}:${t}`)||this._assignmentLogger({unitKey:n,policyId:i.policyId,policyKey:i.policyKey,allocationName:i.allocationName,allocationKey:i.allocationKey,timestamp:e.metadata.timestamp,layerId:i.layerId,allocationId:i.allocationId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,sdkName:he,sdkVersion:x,properties:e.metadata.filteredContext,type:t,decisionId:e.decisionId,anonymousId:this._stableId.getId(),id:ae()})}_applyOverridesToResult(e){let t=Object.keys(this._overrides);if(t.length!==0)for(let n of t)n in e&&(e[n]=this._overrides[n])}_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=O(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 le(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 u=0;u<o.length;u++){let p=s[u];p&&a.set(o[u].policyId,{allocationIndex:p.allocationIndex,entityId:o[u].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>Rt&&(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>=Ot){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 we(r){let e=new P(r);return await e.initialize(),e}function Se(r){return new P(r)}function Ce(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(c,f){try{return new RegExp(c).test(f)}catch{return f===c}}function a(c,f,h){if(f==="innerHTML")c.innerHTML=h;else if(f==="textContent")c.textContent=h;else if(f==="src"&&"src"in c)c.src=h;else if(f==="href"&&"href"in c)c.href=h;else if(f.startsWith("style.")){let m=f.slice(6);c.style[m]=h}else c.setAttribute(f,h)}function u(c,f){let h=String(f);try{let m=document.querySelectorAll(c.selector);for(let E of m)a(E,c.property,h)}catch(m){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${c.parameterKey}:`,m)}}function p(c,f=!1){n=c;let h=typeof window<"u"?window.location.pathname:"";for(let m of t){if(!f&&!s(m.urlPattern,h))continue;let E=c[m.parameterKey];E!==void 0&&u(m,E)}}function v(){o&&clearTimeout(o),o=setTimeout(()=>{p(n)},e.debounceMs)}function g(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{v()}),i.observe(document.body,{childList:!0,subtree:!0}))}function b(){i&&(i.disconnect(),i=null),o&&(clearTimeout(o),o=null)}return{name:"dom-binding",onInitialize(){e.observeMutations&&g()},onConfigUpdate(c){t=c.domBindings??[]},onResolve(c){p(c)},onDecision(c){p(c.assignments)},onDestroy(){b(),t=[],n={}},applyBindings(c){p(c||n)},getBindings(){return t}}}var I=null;async function Mt(r){return I?(console.warn("[Traffical] Client already initialized. Returning existing instance."),I):(I=await we(r),I)}function Lt(r){return I?(console.warn("[Traffical] Client already initialized. Returning existing instance."),I):(I=Se(r),I.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),I)}function Nt(){return I}function Bt(){I&&(I.destroy(),I=null)}return Ne(Kt);})();
|
|
3
3
|
//# sourceMappingURL=traffical.min.js.map
|