@traffical/js-client 0.16.0 → 0.16.2
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/plugins/warehouse-native-logger.d.ts +6 -97
- package/dist/plugins/warehouse-native-logger.d.ts.map +1 -1
- package/dist/plugins/warehouse-native-logger.js +6 -172
- 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,101 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Warehouse-native logger factory.
|
|
2
|
+
* Warehouse-native logger factory — re-export.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
-
import type { AssignmentLogger, TrackableEvent, TrackableEventLogger } from "@traffical/core";
|
|
16
|
-
/** Minimal Segment/Rudderstack analytics surface used by this factory. */
|
|
17
|
-
export interface AnalyticsLike {
|
|
18
|
-
track: (event: string, props: Record<string, unknown>) => void;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Jitsu HTTP destination.
|
|
22
|
-
*
|
|
23
|
-
* Builds Segment-compatible payloads and POSTs them to a Jitsu ingest
|
|
24
|
-
* endpoint. By default the URL is `${host}/api/s/{type}` (client mode) or
|
|
25
|
-
* `${host}/api/s/s2s/{type}` (server-to-server mode). Provide `endpoint` to
|
|
26
|
-
* fully control the URL (e.g. when posting through your own proxy route).
|
|
27
|
-
*/
|
|
28
|
-
export interface JitsuDestination {
|
|
29
|
-
type: "jitsu";
|
|
30
|
-
/** Ingest host, e.g. "https://xxxx.d.jitsu.com" or a proxy base like "/api/jitsu". */
|
|
31
|
-
host: string;
|
|
32
|
-
/** Server write key. Sent as the `X-Write-Key` header (s2s only). Omit when proxying. */
|
|
33
|
-
writeKey?: string;
|
|
34
|
-
/** "client" (browser) or "s2s" (server-to-server). Default: "client". */
|
|
35
|
-
mode?: "client" | "s2s";
|
|
36
|
-
/** Jitsu event-type path segment. Default: "track". */
|
|
37
|
-
eventTypePath?: "page" | "track" | "identify" | "group" | "event";
|
|
38
|
-
/** Override the destination URL builder. Receives the event-type path segment. */
|
|
39
|
-
endpoint?: (type: string) => string;
|
|
40
|
-
/** Custom fetch implementation (defaults to global fetch). */
|
|
41
|
-
fetchImpl?: typeof fetch;
|
|
42
|
-
}
|
|
43
|
-
export interface WarehouseNativeLoggerOptions {
|
|
44
|
-
/** Where to send data. */
|
|
45
|
-
destination: ({
|
|
46
|
-
type: "segment";
|
|
47
|
-
} & {
|
|
48
|
-
analytics: AnalyticsLike;
|
|
49
|
-
}) | ({
|
|
50
|
-
type: "rudderstack";
|
|
51
|
-
} & {
|
|
52
|
-
analytics: AnalyticsLike;
|
|
53
|
-
}) | JitsuDestination | {
|
|
54
|
-
type: "custom";
|
|
55
|
-
/** @deprecated Use `assignmentHandler`. Kept for back-compat. */
|
|
56
|
-
handler?: AssignmentLogger;
|
|
57
|
-
/** Handler for structured assignment rows. */
|
|
58
|
-
assignmentHandler?: AssignmentLogger;
|
|
59
|
-
/** Handler for full events (exposure/track/decision). */
|
|
60
|
-
eventHandler?: TrackableEventLogger;
|
|
61
|
-
};
|
|
62
|
-
/** Event name used for assignment rows (default: "Experiment Assignment"). */
|
|
63
|
-
eventName?: string;
|
|
64
|
-
/** Maps a full event (exposure/track/decision) to a destination event name. */
|
|
65
|
-
eventNameFor?: (event: TrackableEvent) => string;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Creates both an `assignmentLogger` and an `eventLogger` for the configured
|
|
69
|
-
* destination. Pass either (or both) to the TrafficalClient options.
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```ts
|
|
73
|
-
* const { assignmentLogger, eventLogger } = createWarehouseNativeLogger({
|
|
74
|
-
* destination: { type: "jitsu", host: "/api/jitsu", mode: "s2s" },
|
|
75
|
-
* });
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
export declare function createWarehouseNativeLogger(options: WarehouseNativeLoggerOptions): {
|
|
79
|
-
assignmentLogger: AssignmentLogger;
|
|
80
|
-
eventLogger: TrackableEventLogger;
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Creates an AssignmentLogger that routes structured assignment entries
|
|
84
|
-
* to Segment, Rudderstack, Jitsu, or a custom handler.
|
|
85
|
-
*
|
|
86
|
-
* Back-compat wrapper around {@link createWarehouseNativeLogger}.
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* ```ts
|
|
90
|
-
* import { createWarehouseNativeLoggerPlugin } from "@traffical/js-client";
|
|
91
|
-
*
|
|
92
|
-
* const client = new TrafficalClient({
|
|
93
|
-
* // ...
|
|
94
|
-
* assignmentLogger: createWarehouseNativeLoggerPlugin({
|
|
95
|
-
* destination: { type: "segment", analytics },
|
|
96
|
-
* }),
|
|
97
|
-
* });
|
|
98
|
-
* ```
|
|
4
|
+
* The implementation moved to `@traffical/core-io` so that server-side SDKs
|
|
5
|
+
* (`@traffical/node`) share it rather than re-deriving it. This module stays
|
|
6
|
+
* as the public import path for browser consumers; `@traffical/js-client`
|
|
7
|
+
* continues to export the same symbols.
|
|
99
8
|
*/
|
|
100
|
-
export
|
|
9
|
+
export { createWarehouseNativeLogger, createWarehouseNativeLoggerPlugin, type WarehouseNativeLoggerOptions, type JitsuDestination, type AnalyticsLike, } from "@traffical/core-io";
|
|
101
10
|
//# sourceMappingURL=warehouse-native-logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warehouse-native-logger.d.ts","sourceRoot":"","sources":["../../src/plugins/warehouse-native-logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"warehouse-native-logger.d.ts","sourceRoot":"","sources":["../../src/plugins/warehouse-native-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,KAAK,4BAA4B,EACjC,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC"}
|
|
@@ -1,176 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Warehouse-native logger factory.
|
|
2
|
+
* Warehouse-native logger factory — re-export.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
-
bucket: entry.bucket,
|
|
33
|
-
propensity: entry.probability,
|
|
34
|
-
model_version: entry.modelVersion,
|
|
35
|
-
config_version: entry.configVersion,
|
|
36
|
-
...entry.properties,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/** Default destination event name for a full event. */
|
|
40
|
-
function defaultEventName(event) {
|
|
41
|
-
switch (event.type) {
|
|
42
|
-
case "exposure":
|
|
43
|
-
return "traffical_exposure";
|
|
44
|
-
case "decision":
|
|
45
|
-
return "traffical_decision";
|
|
46
|
-
case "track":
|
|
47
|
-
default:
|
|
48
|
-
return event.event;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
/** Flattens a full event to a properties object suitable for analytics/Jitsu. */
|
|
52
|
-
function toEventProps(event) {
|
|
53
|
-
const common = {
|
|
54
|
-
unit_key: event.unitKey,
|
|
55
|
-
org_id: event.orgId,
|
|
56
|
-
project_id: event.projectId,
|
|
57
|
-
env: event.env,
|
|
58
|
-
type: event.type,
|
|
59
|
-
event_id: event.id,
|
|
60
|
-
};
|
|
61
|
-
if (event.type === "track") {
|
|
62
|
-
return {
|
|
63
|
-
...common,
|
|
64
|
-
decision_id: event.decisionId,
|
|
65
|
-
value: event.value,
|
|
66
|
-
...event.properties,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
// exposure | decision
|
|
70
|
-
return {
|
|
71
|
-
...common,
|
|
72
|
-
decision_id: event.type === "exposure" ? event.decisionId : event.id,
|
|
73
|
-
assignments: event.assignments,
|
|
74
|
-
...(event.context ?? {}),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
/** Builds a Jitsu/Segment envelope for a track-style payload. */
|
|
78
|
-
function jitsuEnvelope(eventName, identity, properties) {
|
|
79
|
-
return {
|
|
80
|
-
type: "track",
|
|
81
|
-
event: eventName,
|
|
82
|
-
userId: identity.unitKey,
|
|
83
|
-
anonymousId: identity.anonymousId,
|
|
84
|
-
messageId: identity.messageId,
|
|
85
|
-
timestamp: identity.timestamp ?? new Date().toISOString(),
|
|
86
|
-
properties,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
/** Creates a sender that POSTs Segment-compatible payloads to Jitsu. */
|
|
90
|
-
function createJitsuSender(dest) {
|
|
91
|
-
const fetchImpl = dest.fetchImpl ?? globalThis.fetch;
|
|
92
|
-
const typePath = dest.eventTypePath ?? "track";
|
|
93
|
-
const buildUrl = dest.endpoint
|
|
94
|
-
? dest.endpoint
|
|
95
|
-
: (type) => `${dest.host.replace(/\/$/, "")}/api/s/${dest.mode === "s2s" ? "s2s/" : ""}${type}`;
|
|
96
|
-
const url = buildUrl(typePath);
|
|
97
|
-
return (body) => {
|
|
98
|
-
if (!fetchImpl)
|
|
99
|
-
return;
|
|
100
|
-
const headers = { "Content-Type": "application/json" };
|
|
101
|
-
if (dest.writeKey)
|
|
102
|
-
headers["X-Write-Key"] = dest.writeKey;
|
|
103
|
-
try {
|
|
104
|
-
void fetchImpl(url, {
|
|
105
|
-
method: "POST",
|
|
106
|
-
headers,
|
|
107
|
-
body: JSON.stringify(body),
|
|
108
|
-
// Best-effort delivery on page unload in browsers.
|
|
109
|
-
keepalive: true,
|
|
110
|
-
}).catch(() => {
|
|
111
|
-
// Swallow network errors — BYO delivery is best-effort.
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
// Swallow synchronous errors (e.g. fetch unavailable).
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Creates both an `assignmentLogger` and an `eventLogger` for the configured
|
|
121
|
-
* destination. Pass either (or both) to the TrafficalClient options.
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* ```ts
|
|
125
|
-
* const { assignmentLogger, eventLogger } = createWarehouseNativeLogger({
|
|
126
|
-
* destination: { type: "jitsu", host: "/api/jitsu", mode: "s2s" },
|
|
127
|
-
* });
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
export function createWarehouseNativeLogger(options) {
|
|
131
|
-
const dest = options.destination;
|
|
132
|
-
const assignmentEventName = options.eventName ?? DEFAULT_ASSIGNMENT_EVENT_NAME;
|
|
133
|
-
const nameFor = options.eventNameFor ?? defaultEventName;
|
|
134
|
-
if (dest.type === "custom") {
|
|
135
|
-
const assignmentHandler = dest.assignmentHandler ?? dest.handler;
|
|
136
|
-
return {
|
|
137
|
-
assignmentLogger: (entry) => assignmentHandler?.(entry),
|
|
138
|
-
eventLogger: (event) => dest.eventHandler?.(event),
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
if (dest.type === "jitsu") {
|
|
142
|
-
const send = createJitsuSender(dest);
|
|
143
|
-
return {
|
|
144
|
-
assignmentLogger: (entry) => send(jitsuEnvelope(assignmentEventName, { unitKey: entry.unitKey, anonymousId: entry.anonymousId, messageId: entry.id, timestamp: entry.timestamp }, toAssignmentProps(entry))),
|
|
145
|
-
eventLogger: (event) => send(jitsuEnvelope(nameFor(event), { unitKey: event.unitKey, messageId: event.id, timestamp: event.timestamp }, toEventProps(event))),
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
// segment | rudderstack
|
|
149
|
-
const analytics = dest.analytics;
|
|
150
|
-
return {
|
|
151
|
-
assignmentLogger: (entry) => analytics.track(assignmentEventName, toAssignmentProps(entry)),
|
|
152
|
-
eventLogger: (event) => analytics.track(nameFor(event), toEventProps(event)),
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Creates an AssignmentLogger that routes structured assignment entries
|
|
157
|
-
* to Segment, Rudderstack, Jitsu, or a custom handler.
|
|
158
|
-
*
|
|
159
|
-
* Back-compat wrapper around {@link createWarehouseNativeLogger}.
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* ```ts
|
|
163
|
-
* import { createWarehouseNativeLoggerPlugin } from "@traffical/js-client";
|
|
164
|
-
*
|
|
165
|
-
* const client = new TrafficalClient({
|
|
166
|
-
* // ...
|
|
167
|
-
* assignmentLogger: createWarehouseNativeLoggerPlugin({
|
|
168
|
-
* destination: { type: "segment", analytics },
|
|
169
|
-
* }),
|
|
170
|
-
* });
|
|
171
|
-
* ```
|
|
4
|
+
* The implementation moved to `@traffical/core-io` so that server-side SDKs
|
|
5
|
+
* (`@traffical/node`) share it rather than re-deriving it. This module stays
|
|
6
|
+
* as the public import path for browser consumers; `@traffical/js-client`
|
|
7
|
+
* continues to export the same symbols.
|
|
172
8
|
*/
|
|
173
|
-
export
|
|
174
|
-
return createWarehouseNativeLogger(options).assignmentLogger;
|
|
175
|
-
}
|
|
9
|
+
export { createWarehouseNativeLogger, createWarehouseNativeLoggerPlugin, } from "@traffical/core-io";
|
|
176
10
|
//# 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":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,GAIlC,MAAM,oBAAoB,CAAC"}
|
package/dist/traffical.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/* @traffical/js-client v0.16.
|
|
2
|
-
"use strict";var Traffical=(()=>{var q=Object.defineProperty;var it=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var ot=Object.prototype.hasOwnProperty;var st=(r,e,t)=>e in r?q(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var at=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ct=(r,e)=>{for(var t in e)q(r,t,{get:e[t],enumerable:!0})},lt=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of rt(e))!ot.call(r,i)&&i!==t&&q(r,i,{get:()=>e[i],enumerable:!(n=it(e,i))||n.enumerable});return r};var ut=r=>lt(q({},"__esModule",{value:!0}),r);var m=(r,e,t)=>(st(r,typeof e!="symbol"?e+"":e,t),t);var He=at(()=>{});var En={};ct(En,{TrafficalClient:()=>M,createDOMBindingPlugin:()=>nt,createDebugPlugin:()=>Me,createRedirectAttributionPlugin:()=>Le,createRedirectPlugin:()=>Re,destroy:()=>xn,init:()=>vn,initSync:()=>_n,instance:()=>bn});function dt(r){return r instanceof Uint8Array||ArrayBuffer.isView(r)&&r.constructor.name==="Uint8Array"&&"BYTES_PER_ELEMENT"in r&&r.BYTES_PER_ELEMENT===1}function he(r,e,t=""){let n=dt(r),i=r?.length,o=e!==void 0;if(!n||o&&i!==e){let s=t&&`"${t}" `,a=o?` of length ${e}`:"",c=n?`length=${i}`:`type=${typeof r}`,f=s+"expected Uint8Array"+a+", got "+c;throw n?new RangeError(f):new TypeError(f)}return r}function pe(r,e=!0){if(r.destroyed)throw new Error("Hash instance has been destroyed");if(e&&r.finished)throw new Error("Hash#digest() has already been called")}function Be(r,e){he(r,void 0,"digestInto() output");let t=e.outputLen;if(r.length<t)throw new RangeError('"digestInto() output" expected to be of length >='+t)}function B(...r){for(let e=0;e<r.length;e++)r[e].fill(0)}function X(r){return new DataView(r.buffer,r.byteOffset,r.byteLength)}function I(r,e){return r<<32-e|r>>>e}function Ne(r,e={}){let t=(i,o)=>r(o).update(i).digest(),n=r(void 0);return t.outputLen=n.outputLen,t.blockLen=n.blockLen,t.canXOF=n.canXOF,t.create=i=>r(i),Object.assign(t,e),Object.freeze(t)}var Ve=r=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,r])});function Ue(r,e,t){return r&e^~r&t}function Fe(r,e,t){return r&e^r&t^e&t}var J=class{constructor(e,t,n,i){m(this,"blockLen");m(this,"outputLen");m(this,"canXOF",!1);m(this,"padOffset");m(this,"isLE");m(this,"buffer");m(this,"view");m(this,"finished",!1);m(this,"length",0);m(this,"pos",0);m(this,"destroyed",!1);this.blockLen=e,this.outputLen=t,this.padOffset=n,this.isLE=i,this.buffer=new Uint8Array(e),this.view=X(this.buffer)}update(e){pe(this),he(e);let{view:t,buffer:n,blockLen:i}=this,o=e.length;for(let s=0;s<o;){let a=Math.min(i-this.pos,o-s);if(a===i){let c=X(e);for(;i<=o-s;s+=i)this.process(c,s);continue}n.set(e.subarray(s,s+a),this.pos),this.pos+=a,s+=a,this.pos===i&&(this.process(t,0),this.pos=0)}return this.length+=e.length,this.roundClean(),this}digestInto(e){pe(this),Be(e,this),this.finished=!0;let{buffer:t,view:n,blockLen:i,isLE:o}=this,{pos:s}=this;t[s++]=128,B(this.buffer.subarray(s)),this.padOffset>i-s&&(this.process(n,0),s=0);for(let l=s;l<i;l++)t[l]=0;n.setBigUint64(i-8,BigInt(this.length*8),o),this.process(n,0);let a=X(e),c=this.outputLen;if(c%4)throw new Error("_sha2: outputLen must be aligned to 32bit");let f=c/4,h=this.get();if(f>h.length)throw new Error("_sha2: outputLen bigger than state");for(let l=0;l<f;l++)a.setUint32(4*l,h[l],o)}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let n=e.slice(0,t);return this.destroy(),n}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());let{blockLen:t,buffer:n,length:i,finished:o,destroyed:s,pos:a}=this;return e.destroyed=s,e.finished=o,e.length=i,e.pos=a,i%t&&e.buffer.set(n),e}clone(){return this._cloneInto()}},k=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var ft=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),S=new Uint32Array(64),me=class extends J{constructor(e){super(64,e,8,!1)}get(){let{A:e,B:t,C:n,D:i,E:o,F:s,G:a,H:c}=this;return[e,t,n,i,o,s,a,c]}set(e,t,n,i,o,s,a,c){this.A=e|0,this.B=t|0,this.C=n|0,this.D=i|0,this.E=o|0,this.F=s|0,this.G=a|0,this.H=c|0}process(e,t){for(let l=0;l<16;l++,t+=4)S[l]=e.getUint32(t,!1);for(let l=16;l<64;l++){let _=S[l-15],u=S[l-2],g=I(_,7)^I(_,18)^_>>>3,y=I(u,17)^I(u,19)^u>>>10;S[l]=y+S[l-7]+g+S[l-16]|0}let{A:n,B:i,C:o,D:s,E:a,F:c,G:f,H:h}=this;for(let l=0;l<64;l++){let _=I(a,6)^I(a,11)^I(a,25),u=h+_+Ue(a,c,f)+ft[l]+S[l]|0,y=(I(n,2)^I(n,13)^I(n,22))+Fe(n,i,o)|0;h=f,f=c,c=a,a=s+u|0,s=o,o=i,i=n,n=u+y|0}n=n+this.A|0,i=i+this.B|0,o=o+this.C|0,s=s+this.D|0,a=a+this.E|0,c=c+this.F|0,f=f+this.G|0,h=h+this.H|0,this.set(n,i,o,s,a,c,f,h)}roundClean(){B(S)}destroy(){this.destroyed=!0,this.set(0,0,0,0,0,0,0,0),B(this.buffer)}},ye=class extends me{constructor(){super(32);m(this,"A",k[0]|0);m(this,"B",k[1]|0);m(this,"C",k[2]|0);m(this,"D",k[3]|0);m(this,"E",k[4]|0);m(this,"F",k[5]|0);m(this,"G",k[6]|0);m(this,"H",k[7]|0)}};var Ke=Ne(()=>new ye,Ve(1));var $e=new TextEncoder,ve="v2";function Q(r){return $e.encode(r).length}function Y(r,e){let t=Q(r),n=Q(e);return`traffical:assignment:${ve}|u:${t}:${r}|l:${n}:${e}`}function N(r){return Ke($e.encode(r))}function V(r){let e=0n;for(let t=0;t<8;t++)e=e<<8n|BigInt(r[t]);return e}function Z(r){return V(N(r))}function ee(r,e,t){let n=N(Y(r,e)),i=V(n);return Number(i%BigInt(t))}function _e(r,e){return r>=e[0]&&r<=e[1]}function te(r,e){for(let t of e)if(_e(r,t.bucketRange))return t;return null}var gt=1n<<53n,ht=9007199254740992;function R(r,e){if(r.length===0||r.length===1)return 0;let t=Z(e),n=Number(t%gt)/ht,i=0;for(let o=0;o<r.length;o++)if(i+=r[o],n<i)return o;return r.length-1}function be(r,e){let{field:t,op:n,value:i,values:o}=r,s=yt(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 ne(r,e){return r.length===0?!0:r.every(t=>be(t,e))}function yt(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 xe(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 Ee(r,e){if(r.length===0)return[];if(r.length===1)return[1];let t=Math.max(e,1e-10),n=r.map(a=>a/t),i=Math.max(...n),o=n.map(a=>Math.exp(a-i)),s=o.reduce((a,c)=>a+c,0);return o.map(a=>a/s)}function Te(r,e){if(r.length===0)return[];if(e<=0)return r;let t=r.length,n=1/t,i=Math.min(e,n),o=r.map(a=>Math.max(a,i)),s=o.reduce((a,c)=>a+c,0);return s===0?Array(t).fill(1/t):o.map(a=>a/s)}function ie(r,e,t){let n=r.contextualModel;if(!n||r.allocations.length===0)return null;let i=vt(n,r.allocations,e),o=Ee(i,n.gamma),s=Te(o,n.actionProbabilityFloor),a=`ctx:${t}:${r.id}`,c=R(s,a);return{allocation:r.allocations[c],probability:s[c]}}function vt(r,e,t){return e.map(n=>{let i=r.coefficients[n.name];return i?xe(i,t):r.defaultAllocationScore})}var _t=r=>crypto.getRandomValues(new Uint8Array(r)),bt=(r,e,t)=>{let n=(2<<Math.log2(r.length-1))-1,i=-~(1.6*n*e/r.length);return(o=e)=>{let s="";for(;;){let a=t(i),c=i|0;for(;c--;)if(s+=r[a[c]&n]||"",s.length>=o)return s}}},je=(r,e=21)=>bt(r,e|0,_t);function re(r){let e=new Error(r);return e.source="ulid",e}var Ie="0123456789ABCDEFGHJKMNPQRSTVWXYZ",U=Ie.length,We=Math.pow(2,48)-1,xt=10,Et=16;function Tt(r){let e=Math.floor(r()*U);return e===U&&(e=U-1),Ie.charAt(e)}function It(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>We)throw re("cannot encode time greater than "+We);if(r<0)throw re("time must be positive");if(Number.isInteger(Number(r))===!1)throw re("time must be an integer");let t,n="";for(;e>0;e--)t=r%U,n=Ie.charAt(t)+n,r=(r-t)/U;return n}function wt(r,e){let t="";for(;r>0;r--)t=Tt(e)+t;return t}function At(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=He();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 re("secure crypto unusable, insecure Math.random not allowed")}function Ct(r){return r||(r=At()),function(t){return isNaN(t)&&(t=Date.now()),It(t,xt)+wt(Et,r)}}var ze=Ct();var kt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",St=8,ei=je(kt,St);function F(r){return`${r}_${ze()}`}function L(){return F("dec")}function we(){return F("exp")}function Ae(){return F("trk")}function Ce(){return F("asn")}function Dt(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 Pt(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 Ge(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function Rt(r,e,t,n){let i=r.entityState?.[e];if(!i)return Ge(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:Ge(n)}function Lt(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=Pt(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let l=i.dynamicAllocations.countKey,_=t[l];if(typeof _!="number"||_<=0)return null;a=Math.floor(_),s=Array.from({length:a},(u,g)=>({id:`${e.id}_dynamic_${g}`,name:String(g),bucketRange:[0,0],overrides:{}}))}else s=e.allocations,a=s.length;if(a===0)return null;let c=Rt(r,e.id,o,a),f=`${o}:${n}:${e.id}`,h=R(c,f);return{allocation:s[h],weight:c[h],entityId:o}}function K(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function oe(r){return r?.hashing?.unitKey??null}function se(r,e){return r?r.parameters.find(n=>n.key===e)?.layerId??null:null}function qe(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=K(r,e)??"",c=new Set(Object.keys(t)),f=r.parameters.filter(l=>c.has(l.key));for(let l of f)l.key in i&&(i[l.key]=l.default);let h=new Map;for(let l of f){let _=h.get(l.layerId)||[];_.push(l),h.set(l.layerId,_)}for(let l of r.layers){let _=h.get(l.id),u=_&&_.length>0,g=l.unitKey,y=g!=null;if(y&&String(g).trim()===""){o.push({layerId:l.id,bucket:-1,...u?{}:{attributionOnly:!0}});continue}let b=y?String(e[g]??""):a;if(!b){o.push({layerId:l.id,bucket:-1,...y?{unitKey:g,unitKeyValue:""}:{},...u?{}:{attributionOnly:!0}});continue}let w=ee(b,l.id,r.hashing.bucketCount),d,v,A,O;for(let p of l.policies)if(p.state==="running"){if(p.eligibleBucketRange){let{start:x,end:E}=p.eligibleBucketRange;if(w<x||w>E)continue}if(ne(p.conditions,e)){if(p.contextualModel){let x=ie(p,e,b);if(x){if(d=p,v=x.allocation,A=x.probability,O=p.contextualModel.generatedAt??p.contextualModel.modelVersion,s.push(p),u)for(let[E,C]of Object.entries(x.allocation.overrides))E in i&&(i[E]=C);break}}if(p.entityConfig&&p.entityConfig.resolutionMode==="bundle"){let x=Lt(r,p,e,b);if(x){if(d=p,v=x.allocation,A=x.weight,s.push(p),u&&!p.entityConfig.dynamicAllocations)for(let[E,C]of Object.entries(x.allocation.overrides))E in i&&(i[E]=C);break}}else if(p.entityConfig&&p.entityConfig.resolutionMode==="edge"){let x=n?.edgeResults?.get(p.id);if(x){if(d=p,s.push(p),p.entityConfig.dynamicAllocations)v={id:`${p.id}_dynamic_${x.allocationIndex}`,name:String(x.allocationIndex),bucketRange:[0,0],overrides:{}};else if(p.allocations[x.allocationIndex]&&(v=p.allocations[x.allocationIndex],u&&v))for(let[E,C]of Object.entries(v.overrides))E in i&&(i[E]=C);break}continue}else{let x=te(w,p.allocations);if(x){if(d=p,v=x,p.kind==="adaptive"){let[E,C]=x.bucketRange;A=(C-E+1)/r.hashing.bucketCount}if(s.push(p),u)for(let[E,C]of Object.entries(x.overrides))E in i&&(i[E]=C);break}}}}o.push({layerId:l.id,bucket:w,policyId:d?.id,policyKey:d?.key,allocationId:v?.id,allocationName:v?.name,allocationKey:v?.key,...A!==void 0&&A>0&&A<=1?{probability:A}:{},...O!==void 0?{modelVersion:O}:{},...y?{unitKey:g,unitKeyValue:b}:{},...u?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function ae(r,e,t,n){return qe(r,e,t,n).assignments}function ce(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=qe(r,e,t,n),c=Dt(e,a);return{decisionId:L(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:c,...r?.version?{configVersion:r.version}:{}}}}var P=class r{constructor(e={}){m(this,"_seen",new Map);m(this,"_ttlMs");m(this,"_maxEntries");m(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 $=class{constructor(e){m(this,"config");m(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 ke(r,e,t,n,i){let o=[];for(let a of e){let c=t[a];if(c==null)return null;o.push(String(c))}let s=o.join("_");return{policyId:r,entityId:s,unitKeyValue:n,allocationCount:i,context:t}}var le=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 j="failed_events";var ue=class{constructor(e){this._queue=[];this._flushTimer=null;this._isFlushing=!1;this._isDisabled=!1;this._droppedCount=0;this._endpoint=e.endpoint,this._apiKey=e.apiKey,this._storage=e.storage,this._batchSize=e.batchSize??10,this._flushIntervalMs=e.flushIntervalMs??3e4,this._requestTimeoutMs=e.requestTimeoutMs??1e4,this._maxQueueSize=e.maxQueueSize??1e3,this._onError=e.onError,this._onSchemaWarnings=e.onSchemaWarnings,this._lifecycleProvider=e.lifecycleProvider,this._setupListeners(),this._retryFailedEvents(),this._startFlushTimer()}log(e){this._isDisabled||(this._queue.length>=this._maxQueueSize&&(this._queue.shift(),this._droppedCount++),this._queue.push(e),this._queue.length>=this._batchSize&&this.flush())}async flush(){if(this._isFlushing||this._isDisabled||this._queue.length===0)return;this._isFlushing=!0;let e=[...this._queue];this._queue=[];try{let t=await this._sendEvents(e);if(t>=200&&t<300)return;if(t===401){this._disable();return}if(t===429||t>=500){this._persistFailedEvents(e),this._onError?.(new Error(`HTTP ${t}: event delivery failed, will retry`));return}this._onError?.(new Error(`HTTP ${t}: batch rejected, dropping ${e.length} events`))}catch(t){this._persistFailedEvents(e),this._onError?.(t instanceof Error?t:new Error(String(t)))}finally{this._isFlushing=!1}}_disable(){this._isDisabled||(this._isDisabled=!0,this._queue=[],this._storage.remove(j),console.warn("[Traffical] API key rejected (HTTP 401); event delivery disabled for this client"))}get droppedCount(){return this._droppedCount}get isDisabled(){return this._isDisabled}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=new AbortController,n=setTimeout(()=>t.abort(),this._requestTimeoutMs),i;try{i=await fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e}),signal:t.signal})}finally{clearTimeout(n)}if(!i.ok)return i.status;if(this._onSchemaWarnings)try{let o=await i.json();o.schemaWarnings&&o.schemaWarnings.length>0&&this._onSchemaWarnings(o.schemaWarnings)}catch{}return i.status}_persistFailedEvents(e){let n=[...this._storage.get(j)??[],...e].slice(-100);this._storage.set(j,n)}_retryFailedEvents(){let e=this._storage.get(j);!e||e.length===0||(this._storage.remove(j),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 H="exposure_dedup";var W=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(H)}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(H)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(H,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(H);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(H);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var z="stable_id",Xt="traffical_sid";var de=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??Xt}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(z);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(z,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(z),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(z)!==null||this._getCookie()!==null}_persist(e){this._storage.set(z,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 G="traffical:",Se=class{constructor(){this._available=this._checkAvailability()}get(e){if(!this._available)return null;try{let t=localStorage.getItem(G+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(G+e,JSON.stringify(i))}catch{}}remove(e){if(this._available)try{localStorage.removeItem(G+e)}catch{}}clear(){if(this._available)try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n?.startsWith(G)&&e.push(n)}e.forEach(t=>localStorage.removeItem(t))}catch{}}_checkAvailability(){try{let e=G+"__test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}},De=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 Xe(){let r=new Se;return r.get("__check__")!==null||Jt()?r:new De}function Jt(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var D="0.16.0";var Qt="js-client";function Pe(r,e){let t=new P({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=P.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,configVersion:n.metadata.configVersion??e.getConfigVersion?.()??void 0,sdkName:Qt,sdkVersion:D};e.log(s)},onDestroy(){t.clear()}}}var Yt="traffical_rdr";function Zt(r,e,t){if(!(typeof document>"u"))try{document.cookie=`${r}=${encodeURIComponent(e)}; max-age=${t}; path=/; SameSite=Lax`}catch{}}function Re(r={}){let e=r.parameterKey??"redirect.url",t=r.compareMode??"pathname",n=r.cookieName??Yt;return{name:"redirect",onInitialize(i){typeof window>"u"||i.decide({context:{},defaults:{[e]:""}})},onBeforeDecision(i){return typeof window>"u"?i:{"url.pathname":window.location.pathname,...i}},onDecision(i){let o=i.assignments[e];if(typeof o!="string"||!o)return;let s=t==="href"?window.location.href:window.location.pathname;if(o===s)return;let a=i.metadata.layers.find(c=>c.policyId&&c.allocationName);a&&Zt(n,JSON.stringify({l:a.layerId,p:a.policyId,a:a.allocationName,ts:Date.now()}),86400),window.location.replace(o)}}}var en="traffical_rdr";function tn(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 nn(r,e){let t=tn(r);if(!t)return null;try{let n=JSON.parse(t);return Date.now()-n.ts>e?null:{layerId:n.l,policyId:n.p,allocationName:n.a}}catch{return null}}function Le(r={}){let e=r.cookieName??en,t=r.expiryMs??864e5;function n(i){let o=nn(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 fe=[],Je={};function rn(){if(typeof window>"u")return{version:1,instances:Je,subscribe:()=>()=>{}};if(!window.__TRAFFICAL_DEBUG__){let r={version:1,instances:Je,subscribe(e){return fe.push(e),()=>{fe=fe.filter(t=>t!==e)}}};window.__TRAFFICAL_DEBUG__=r}return window.__TRAFFICAL_DEBUG__}function Qe(r){for(let e of fe)try{e(r)}catch{}}var on=0;function sn(){return`traffical_${Date.now().toString(36)}_${(++on).toString(36)}`}function an(){return`evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}var cn="traffical-debug";function Me(r={}){let e=r.instanceId??sn(),t=r.maxEvents??500,n=null,i=null,o={},s=[],a=null,c=null,f=[],h=[],l=[];function _(){return{ready:n?.isInitialized===!0,stableId:n?.getStableId?.()??null,effectiveUnitKey:c,configVersion:n?.getConfigVersion?.()??null,assignments:{...o},layers:[...s],lastDecisionId:a,overrides:n?.getOverrides?.()??{}}}function u(){let d=_();for(let v of h)try{v(d)}catch{}}function g(d,v){let A={id:an(),type:d,timestamp:Date.now(),data:v};f.push(A),f.length>t&&f.splice(0,f.length-t);for(let O of l)try{O(A)}catch{}}function y(){if(n)try{n.decide({context:{},defaults:{}})}catch{}}let b={id:e,meta:{orgId:"",projectId:"",env:"",sdkVersion:D},getState:_,subscribe(d){return h.push(d),()=>{h=h.filter(v=>v!==d)}},getEvents(d){return d!==void 0?f.slice(-d):[...f]},onEvent(d){return l.push(d),()=>{l=l.filter(v=>v!==d)}},getConfigBundle(){return i},setUnitKey(d){n?.identify?n.identify(d):n?.setStableId&&n.setStableId(d),u()},setOverride(d,v){n?.applyOverrides&&n.applyOverrides({[d]:v}),u(),y()},clearOverride(d){if(n?.getOverrides&&n?.applyOverrides){let v=n.getOverrides();delete v[d],n.clearOverrides?.(),n.applyOverrides(v)}u(),y()},clearAllOverrides(){n?.clearOverrides?.(),u(),y()},getOverrides(){return n?.getOverrides?.()??{}},reDecide(){y()},async refresh(){n?.refreshConfig&&await n.refreshConfig()}};return{name:cn,onInitialize(d){n=d,i&&(b.meta.orgId=i.orgId,b.meta.projectId=i.projectId,b.meta.env=i.env);let v=rn();v.instances[e]=b,Qe({type:"register",instanceId:e}),u()},onConfigUpdate(d){i=d,b.meta.orgId=d.orgId,b.meta.projectId=d.projectId,b.meta.env=d.env,u()},onDecision(d){o={...d.assignments},s=d.metadata?.layers?[...d.metadata.layers]:[],a=d.decisionId,d.metadata?.unitKeyValue&&(c=d.metadata.unitKeyValue),g("decision",d),u()},onResolve(d){o={...d},u()},onExposure(d){return g("exposure",d),!0},onTrack(d){return g("track",d),!0},onDestroy(){let d=typeof window<"u"?window.__TRAFFICAL_DEBUG__:null;d&&(delete d.instances[e],Qe({type:"unregister",instanceId:e})),h=[],l=[],n=null}}}var ge=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 Ye(){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 Oe="js-client";function Ze(r,e){if(e!==void 0)return{context:r,defaults:e};let t=r;return{context:t.context,defaults:t.defaults}}var ln="https://sdk.traffical.io",un=6e4,dn=1e4,fn=3e5,gn=3e5,hn=100,pn=.1;function mn(r){let e=r*pn;return r+(Math.random()*2-1)*e}function yn(r){if(!r||typeof r!="object")return!1;let e=r;if(!Array.isArray(e.parameters)||!Array.isArray(e.layers))return!1;let t=e.hashing;return!(!t||typeof t!="object"||typeof t.unitKey!="string"||t.unitKey.length===0||typeof t.bucketCount!="number"||!Number.isInteger(t.bucketCount)||t.bucketCount<1)}var M=class{constructor(e){this._state={bundle:null,etag:null,lastFetchTime:0,lastOfflineWarning:0,lastMalformedWarning:0,refreshTimer:null,isInitialized:!1,serverResponse:null,cachedEdgeResults:null};this._decisionCache=new Map;this._cumulativeAttribution=new Map;this._identityListeners=[];this._overrideListeners=[];this._overrides={};this._lastResolveContextKey=null;this._readyPromise=new Promise(e=>{this._readyResolve=e});let t=e.evaluationMode??"bundle";this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??ln,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??un,attributionMode:e.attributionMode??"cumulative",evaluationMode:t},this._requestTimeoutMs=e.configTimeoutMs??e.requestTimeoutMs??dn;let n={baseUrl:this._options.baseUrl,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,apiKey:this._options.apiKey,defaultTimeoutMs:e.resolveTimeoutMs??e.requestTimeoutMs};if(this._decisionClient=new $(n),this._errorBoundary=new le(e.errorBoundary),this._storage=e.storage??Xe(),this._lifecycleProvider=e.lifecycleProvider??Ye(),!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 ue({endpoint:`${this._options.baseUrl}/v1/events/batch`,apiKey:e.apiKey,storage:this._storage,lifecycleProvider:this._lifecycleProvider,batchSize:e.batchSize??e.eventBatchSize,flushIntervalMs:e.flushIntervalMs??e.eventFlushIntervalMs,maxQueueSize:e.eventMaxQueueSize,requestTimeoutMs:e.eventsTimeoutMs??e.requestTimeoutMs,onError:i=>{console.warn("[Traffical] Event logging error:",i.message)},onSchemaWarnings:e.onSchemaWarnings}),this._exposureDedup=new W({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new de({storage:this._storage}),this._plugins=new ge,this._assignmentLogger=e.assignmentLogger,this._byoEventLogger=e.eventLogger,this._disableCloudEvents=e.disableCloudEvents??!1,this._assignmentLoggerDedup=e.deduplicateAssignmentLogger!==!1&&e.assignmentLogger?new W({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}):null,e.trackDecisions!==!1&&(!this._disableCloudEvents||this._byoEventLogger)&&this._plugins.register({plugin:Pe({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:i=>this._dispatchEvent(i),getConfigVersion:()=>this.getConfigVersion()}),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),this._readyResolve()}get isInitialized(){return this._state.isInitialized}async waitForReady(){return this._readyPromise}async close(){if(this._state.refreshTimer&&(clearInterval(this._state.refreshTimer),this._state.refreshTimer=null),this._lifecycleProvider.isUnloading()?this._eventLogger.flushBeacon():await 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)}}}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}getUnitKeyField(){return oe(this._getEffectiveBundle())}getParameterLayerId(e){return se(this._getEffectiveBundle(),e)}getParams(e,t){let{context:n,defaults:i}=Ze(e,t);return this._errorBoundary.capture("getParams",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){this._maybeResolveForContext(n);let c={...i};for(let[f,h]of Object.entries(this._state.serverResponse.assignments))f in c&&(c[f]=h);return this._plugins.runResolve(c),this._applyOverridesToResult(c),c}let o=this._getEffectiveBundle(),s=this._enrichContext(n),a=ae(o,s,i);return this._plugins.runResolve(a),this._applyOverridesToResult(a),a},i)}decide(e,t){let{context:n,defaults:i}=Ze(e,t);return this._errorBoundary.capture("decide",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){this._maybeResolveForContext(n);let f=this._state.serverResponse,h={...i};for(let[_,u]of Object.entries(f.assignments))_ in h&&(h[_]=u);let l={decisionId:L(),assignments:h,metadata:{...f.metadata,configVersion:f.stateVersion}};return this._cacheDecision(l),this._updateCumulativeAttribution(l),this._plugins.runDecision(l),this._applyOverridesToResult(l.assignments),this._emitAssignmentLogEntries(l,"decision"),l}let o=this._getEffectiveBundle(),s=this._enrichContext(n);s=this._plugins.runBeforeDecision(s);let a=this._state.cachedEdgeResults??void 0,c=ce(o,s,i,a);return this._cacheDecision(c),this._updateCumulativeAttribution(c),this._plugins.runDecision(c),this._applyOverridesToResult(c.assignments),this._emitAssignmentLogEntries(c,"decision"),c},{decisionId:L(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:"",layers:[]}})}trackExposure(e){this._errorBoundary.capture("trackExposure",()=>{let t=e.metadata.unitKeyValue;if(!t)return;this._emitAssignmentLogEntries(e,"exposure");let n=e.metadata.configVersion??this.getConfigVersion()??void 0,i=[];for(let s of e.metadata.layers)!s.policyId||!s.allocationName||s.attributionOnly||!this._exposureDedup.checkAndMark(t,s.policyId,s.allocationName)||i.push(s);if(i.length===0)return;let o={type:"exposure",id:we(),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:i,context:e.metadata.filteredContext,configVersion:n,sdkName:Oe,sdkVersion:D};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 n?.value=="number"?n.value:typeof t?.value=="number"?t.value:void 0,s=this._buildAttribution(i,n?.decisionId),a=n?.decisionId,c={type:"track",id:Ae(),orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:i,timestamp:new Date().toISOString(),event:e,value:o,values:n?.values,properties:t,decisionId:a,attribution:s,eventTimestamp:n?.eventTimestamp,sdkName:Oe,sdkVersion:D};this._plugins.runTrack(c)&&this._dispatchEvent(c)},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)return;let i=e.metadata.configVersion??this.getConfigVersion()??void 0;for(let o of e.metadata.layers)!o.policyId||!o.allocationName||this._assignmentLoggerDedup&&!this._assignmentLoggerDedup.checkAndMark(n,o.policyId,`${o.allocationName}:${t}`)||this._assignmentLogger({unitKey:n,policyId:o.policyId,policyKey:o.policyKey,allocationName:o.allocationName,allocationKey:o.allocationKey,timestamp:e.metadata.timestamp,layerId:o.layerId,allocationId:o.allocationId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,sdkName:Oe,sdkVersion:D,properties:e.metadata.filteredContext,type:t,decisionId:e.decisionId,anonymousId:this._stableId.getId(),id:Ce(),bucket:o.bucket>=0?o.bucket:void 0,probability:o.probability,modelVersion:o.modelVersion,configVersion:i})}_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/${encodeURIComponent(this._options.projectId)}?env=${encodeURIComponent(this._options.env)}`,t={"Content-Type":"application/json",Authorization:`Bearer ${this._options.apiKey}`};this._state.etag&&(t["If-None-Match"]=this._state.etag);let n=new AbortController,i=setTimeout(()=>n.abort(),this._requestTimeoutMs);try{let o=await fetch(e,{method:"GET",headers:t,signal:n.signal});if(o.status===304){this._state.lastFetchTime=Date.now();return}if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);let s=await o.json(),a=o.headers.get("ETag");if(!yn(s)){this._logMalformedBundleWarning();return}if(this._state.bundle=s,this._state.etag=a,this._state.lastFetchTime=Date.now(),this._findEdgePolicies(s).length>0){let c=await this._prefetchEdgeResults(s,this._enrichContext({}));this._state.cachedEdgeResults=c}else this._state.cachedEdgeResults=null;this._plugins.runConfigUpdate(s)}catch(o){this._logOfflineWarning(o)}finally{clearTimeout(i)}}_startBackgroundRefresh(){let e=this._options.evaluationMode==="server"?this._state.serverResponse?.suggestedRefreshMs??this._options.refreshIntervalMs:this._options.refreshIntervalMs;if(e<=0)return;let t=()=>{this._state.refreshTimer=setTimeout(()=>{t(),this._options.evaluationMode==="server"?this._fetchServerResolve().catch(()=>{}):this._fetchConfig().catch(()=>{})},mn(e))};t()}_maybeResolveForContext(e){let t=this._enrichContext(e),n;try{n=JSON.stringify(t)}catch{n=""}n!==this._lastResolveContextKey&&(this._lastResolveContextKey=n,this._fetchServerResolve(t))}async _fetchServerResolve(e){if(this._decisionClient)try{let t=e??this._enrichContext({}),n=await this._decisionClient.resolve({context:t});n&&(this._state.serverResponse=n,this._state.lastFetchTime=Date.now())}catch(t){this._logOfflineWarning(t)}}_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=K(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 ke(s.id,s.entityConfig.entityKeys,t,i,a||void 0)}).filter(s=>s!==null);if(o.length===0)return{};try{let s=await this._decisionClient.decideEntityBatch(o),a=new Map;for(let c=0;c<o.length;c++){let f=s[c];f&&a.set(o[c].policyId,{allocationIndex:f.allocationIndex,entityId:o[c].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>fn&&(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)}_logMalformedBundleWarning(){let e=Date.now();e-this._state.lastMalformedWarning>gn&&(console.warn(`[Traffical] Discarded malformed config bundle (invalid hashing/shape). Using ${this._state.bundle?"cached":"local"} config.`),this._state.lastMalformedWarning=e)}_cacheDecision(e){if(this._decisionCache.size>=hn){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 et(r){let e=new M(r);return await e.initialize(),e}function tt(r){return new M(r)}function nt(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(u,g){try{return new RegExp(u).test(g)}catch{return g===u}}function a(u,g,y){if(g==="innerHTML")u.innerHTML=y;else if(g==="textContent")u.textContent=y;else if(g==="src"&&"src"in u)u.src=y;else if(g==="href"&&"href"in u)u.href=y;else if(g.startsWith("style.")){let b=g.slice(6);u.style[b]=y}else u.setAttribute(g,y)}function c(u,g){let y=String(g);try{let b=document.querySelectorAll(u.selector);for(let w of b)a(w,u.property,y)}catch(b){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${u.parameterKey}:`,b)}}function f(u,g=!1){n=u;let y=typeof window<"u"?window.location.pathname:"";for(let b of t){if(!g&&!s(b.urlPattern,y))continue;let w=u[b.parameterKey];w!==void 0&&c(b,w)}}function h(){o&&clearTimeout(o),o=setTimeout(()=>{f(n)},e.debounceMs)}function l(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{h()}),i.observe(document.body,{childList:!0,subtree:!0}))}function _(){i&&(i.disconnect(),i=null),o&&(clearTimeout(o),o=null)}return{name:"dom-binding",onInitialize(){e.observeMutations&&l()},onConfigUpdate(u){t=u.domBindings??[]},onResolve(u){f(u)},onDecision(u){f(u.assignments)},onDestroy(){_(),t=[],n={}},applyBindings(u){f(u||n)},getBindings(){return t}}}var T=null;async function vn(r){return T?(console.warn("[Traffical] Client already initialized. Returning existing instance."),T):(T=await et(r),T)}function _n(r){return T?(console.warn("[Traffical] Client already initialized. Returning existing instance."),T):(T=tt(r),T.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),T)}function bn(){return T}function xn(){T&&(T.destroy(),T=null)}return ut(En);})();
|
|
1
|
+
/* @traffical/js-client v0.16.2 */
|
|
2
|
+
"use strict";var Traffical=(()=>{var q=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var st=Object.getOwnPropertyNames;var at=Object.prototype.hasOwnProperty;var ct=(r,e,t)=>e in r?q(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var lt=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ut=(r,e)=>{for(var t in e)q(r,t,{get:e[t],enumerable:!0})},dt=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of st(e))!at.call(r,i)&&i!==t&&q(r,i,{get:()=>e[i],enumerable:!(n=ot(e,i))||n.enumerable});return r};var ft=r=>dt(q({},"__esModule",{value:!0}),r);var m=(r,e,t)=>(ct(r,typeof e!="symbol"?e+"":e,t),t);var He=lt(()=>{});var In={};ut(In,{TrafficalClient:()=>M,createDOMBindingPlugin:()=>rt,createDebugPlugin:()=>Me,createRedirectAttributionPlugin:()=>Le,createRedirectPlugin:()=>Re,destroy:()=>Tn,init:()=>xn,initSync:()=>bn,instance:()=>En});function gt(r){return r instanceof Uint8Array||ArrayBuffer.isView(r)&&r.constructor.name==="Uint8Array"&&"BYTES_PER_ELEMENT"in r&&r.BYTES_PER_ELEMENT===1}function he(r,e,t=""){let n=gt(r),i=r?.length,o=e!==void 0;if(!n||o&&i!==e){let s=t&&`"${t}" `,a=o?` of length ${e}`:"",c=n?`length=${i}`:`type=${typeof r}`,f=s+"expected Uint8Array"+a+", got "+c;throw n?new RangeError(f):new TypeError(f)}return r}function pe(r,e=!0){if(r.destroyed)throw new Error("Hash instance has been destroyed");if(e&&r.finished)throw new Error("Hash#digest() has already been called")}function Be(r,e){he(r,void 0,"digestInto() output");let t=e.outputLen;if(r.length<t)throw new RangeError('"digestInto() output" expected to be of length >='+t)}function B(...r){for(let e=0;e<r.length;e++)r[e].fill(0)}function X(r){return new DataView(r.buffer,r.byteOffset,r.byteLength)}function I(r,e){return r<<32-e|r>>>e}function Ne(r,e={}){let t=(i,o)=>r(o).update(i).digest(),n=r(void 0);return t.outputLen=n.outputLen,t.blockLen=n.blockLen,t.canXOF=n.canXOF,t.create=i=>r(i),Object.assign(t,e),Object.freeze(t)}var Ve=r=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,r])});function Ue(r,e,t){return r&e^~r&t}function Fe(r,e,t){return r&e^r&t^e&t}var J=class{constructor(e,t,n,i){m(this,"blockLen");m(this,"outputLen");m(this,"canXOF",!1);m(this,"padOffset");m(this,"isLE");m(this,"buffer");m(this,"view");m(this,"finished",!1);m(this,"length",0);m(this,"pos",0);m(this,"destroyed",!1);this.blockLen=e,this.outputLen=t,this.padOffset=n,this.isLE=i,this.buffer=new Uint8Array(e),this.view=X(this.buffer)}update(e){pe(this),he(e);let{view:t,buffer:n,blockLen:i}=this,o=e.length;for(let s=0;s<o;){let a=Math.min(i-this.pos,o-s);if(a===i){let c=X(e);for(;i<=o-s;s+=i)this.process(c,s);continue}n.set(e.subarray(s,s+a),this.pos),this.pos+=a,s+=a,this.pos===i&&(this.process(t,0),this.pos=0)}return this.length+=e.length,this.roundClean(),this}digestInto(e){pe(this),Be(e,this),this.finished=!0;let{buffer:t,view:n,blockLen:i,isLE:o}=this,{pos:s}=this;t[s++]=128,B(this.buffer.subarray(s)),this.padOffset>i-s&&(this.process(n,0),s=0);for(let l=s;l<i;l++)t[l]=0;n.setBigUint64(i-8,BigInt(this.length*8),o),this.process(n,0);let a=X(e),c=this.outputLen;if(c%4)throw new Error("_sha2: outputLen must be aligned to 32bit");let f=c/4,h=this.get();if(f>h.length)throw new Error("_sha2: outputLen bigger than state");for(let l=0;l<f;l++)a.setUint32(4*l,h[l],o)}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let n=e.slice(0,t);return this.destroy(),n}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());let{blockLen:t,buffer:n,length:i,finished:o,destroyed:s,pos:a}=this;return e.destroyed=s,e.finished=o,e.length=i,e.pos=a,i%t&&e.buffer.set(n),e}clone(){return this._cloneInto()}},A=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var ht=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),k=new Uint32Array(64),me=class extends J{constructor(e){super(64,e,8,!1)}get(){let{A:e,B:t,C:n,D:i,E:o,F:s,G:a,H:c}=this;return[e,t,n,i,o,s,a,c]}set(e,t,n,i,o,s,a,c){this.A=e|0,this.B=t|0,this.C=n|0,this.D=i|0,this.E=o|0,this.F=s|0,this.G=a|0,this.H=c|0}process(e,t){for(let l=0;l<16;l++,t+=4)k[l]=e.getUint32(t,!1);for(let l=16;l<64;l++){let _=k[l-15],u=k[l-2],g=I(_,7)^I(_,18)^_>>>3,y=I(u,17)^I(u,19)^u>>>10;k[l]=y+k[l-7]+g+k[l-16]|0}let{A:n,B:i,C:o,D:s,E:a,F:c,G:f,H:h}=this;for(let l=0;l<64;l++){let _=I(a,6)^I(a,11)^I(a,25),u=h+_+Ue(a,c,f)+ht[l]+k[l]|0,y=(I(n,2)^I(n,13)^I(n,22))+Fe(n,i,o)|0;h=f,f=c,c=a,a=s+u|0,s=o,o=i,i=n,n=u+y|0}n=n+this.A|0,i=i+this.B|0,o=o+this.C|0,s=s+this.D|0,a=a+this.E|0,c=c+this.F|0,f=f+this.G|0,h=h+this.H|0,this.set(n,i,o,s,a,c,f,h)}roundClean(){B(k)}destroy(){this.destroyed=!0,this.set(0,0,0,0,0,0,0,0),B(this.buffer)}},ye=class extends me{constructor(){super(32);m(this,"A",A[0]|0);m(this,"B",A[1]|0);m(this,"C",A[2]|0);m(this,"D",A[3]|0);m(this,"E",A[4]|0);m(this,"F",A[5]|0);m(this,"G",A[6]|0);m(this,"H",A[7]|0)}};var Ke=Ne(()=>new ye,Ve(1));var $e=new TextEncoder,ve="v2";function Q(r){return $e.encode(r).length}function Y(r,e){let t=Q(r),n=Q(e);return`traffical:assignment:${ve}|u:${t}:${r}|l:${n}:${e}`}function N(r){return Ke($e.encode(r))}function V(r){let e=0n;for(let t=0;t<8;t++)e=e<<8n|BigInt(r[t]);return e}function Z(r){return V(N(r))}function ee(r,e,t){let n=N(Y(r,e)),i=V(n);return Number(i%BigInt(t))}function _e(r,e){return r>=e[0]&&r<=e[1]}function te(r,e){for(let t of e)if(_e(r,t.bucketRange))return t;return null}var pt=1n<<53n,mt=9007199254740992;function R(r,e){if(r.length===0||r.length===1)return 0;let t=Z(e),n=Number(t%pt)/mt,i=0;for(let o=0;o<r.length;o++)if(i+=r[o],n<i)return o;return r.length-1}function xe(r,e){let{field:t,op:n,value:i,values:o}=r,s=_t(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 ne(r,e){return r.length===0?!0:r.every(t=>xe(t,e))}function _t(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 be(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 Ee(r,e){if(r.length===0)return[];if(r.length===1)return[1];let t=Math.max(e,1e-10),n=r.map(a=>a/t),i=Math.max(...n),o=n.map(a=>Math.exp(a-i)),s=o.reduce((a,c)=>a+c,0);return o.map(a=>a/s)}function Te(r,e){if(r.length===0)return[];if(e<=0)return r;let t=r.length,n=1/t,i=Math.min(e,n),o=r.map(a=>Math.max(a,i)),s=o.reduce((a,c)=>a+c,0);return s===0?Array(t).fill(1/t):o.map(a=>a/s)}function ie(r,e,t){let n=r.contextualModel;if(!n||r.allocations.length===0)return null;let i=xt(n,r.allocations,e),o=Ee(i,n.gamma),s=Te(o,n.actionProbabilityFloor),a=`ctx:${t}:${r.id}`,c=R(s,a);return{allocation:r.allocations[c],probability:s[c]}}function xt(r,e,t){return e.map(n=>{let i=r.coefficients[n.key??n.name];return i?be(i,t):r.defaultAllocationScore})}var bt=r=>crypto.getRandomValues(new Uint8Array(r)),Et=(r,e,t)=>{let n=(2<<Math.log2(r.length-1))-1,i=-~(1.6*n*e/r.length);return(o=e)=>{let s="";for(;;){let a=t(i),c=i|0;for(;c--;)if(s+=r[a[c]&n]||"",s.length>=o)return s}}},je=(r,e=21)=>Et(r,e|0,bt);function re(r){let e=new Error(r);return e.source="ulid",e}var Ie="0123456789ABCDEFGHJKMNPQRSTVWXYZ",U=Ie.length,We=Math.pow(2,48)-1,Tt=10,It=16;function wt(r){let e=Math.floor(r()*U);return e===U&&(e=U-1),Ie.charAt(e)}function Ct(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>We)throw re("cannot encode time greater than "+We);if(r<0)throw re("time must be positive");if(Number.isInteger(Number(r))===!1)throw re("time must be an integer");let t,n="";for(;e>0;e--)t=r%U,n=Ie.charAt(t)+n,r=(r-t)/U;return n}function St(r,e){let t="";for(;r>0;r--)t=wt(e)+t;return t}function At(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=He();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 re("secure crypto unusable, insecure Math.random not allowed")}function kt(r){return r||(r=At()),function(t){return isNaN(t)&&(t=Date.now()),Ct(t,Tt)+St(It,r)}}var ze=kt();var Dt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Pt=8,ni=je(Dt,Pt);function F(r){return`${r}_${ze()}`}function L(){return F("dec")}function we(){return F("exp")}function Ce(){return F("trk")}function Se(){return F("asn")}function Rt(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 Lt(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 Ge(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function Mt(r,e,t,n){let i=r.entityState?.[e];if(!i)return Ge(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:Ge(n)}function Ot(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=Lt(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let l=i.dynamicAllocations.countKey,_=t[l];if(typeof _!="number"||_<=0)return null;a=Math.floor(_),s=Array.from({length:a},(u,g)=>({id:`${e.id}_dynamic_${g}`,name:String(g),bucketRange:[0,0],overrides:{}}))}else s=e.allocations,a=s.length;if(a===0)return null;let c=Mt(r,e.id,o,a),f=`${o}:${n}:${e.id}`,h=R(c,f);return{allocation:s[h],weight:c[h],entityId:o}}function K(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function oe(r){return r?.hashing?.unitKey??null}function se(r,e){return r?r.parameters.find(n=>n.key===e)?.layerId??null:null}function qe(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=K(r,e)??"",c=new Set(Object.keys(t)),f=r.parameters.filter(l=>c.has(l.key));for(let l of f)l.key in i&&(i[l.key]=l.default);let h=new Map;for(let l of f){let _=h.get(l.layerId)||[];_.push(l),h.set(l.layerId,_)}for(let l of r.layers){let _=h.get(l.id),u=_&&_.length>0,g=l.unitKey,y=g!=null;if(y&&String(g).trim()===""){o.push({layerId:l.id,bucket:-1,...u?{}:{attributionOnly:!0}});continue}let x=y?String(e[g]??""):a;if(!x){o.push({layerId:l.id,bucket:-1,...y?{unitKey:g,unitKeyValue:""}:{},...u?{}:{attributionOnly:!0}});continue}let w=ee(x,l.id,r.hashing.bucketCount),d,v,C,O;for(let p of l.policies)if(p.state==="running"){if(p.eligibleBucketRange){let{start:b,end:E}=p.eligibleBucketRange;if(w<b||w>E)continue}if(ne(p.conditions,e)){if(p.contextualModel){let b=ie(p,e,x);if(b){if(d=p,v=b.allocation,C=b.probability,O=p.contextualModel.generatedAt??p.contextualModel.modelVersion,s.push(p),u)for(let[E,S]of Object.entries(b.allocation.overrides))E in i&&(i[E]=S);break}}if(p.entityConfig&&p.entityConfig.resolutionMode==="bundle"){let b=Ot(r,p,e,x);if(b){if(d=p,v=b.allocation,C=b.weight,s.push(p),u&&!p.entityConfig.dynamicAllocations)for(let[E,S]of Object.entries(b.allocation.overrides))E in i&&(i[E]=S);break}}else if(p.entityConfig&&p.entityConfig.resolutionMode==="edge"){let b=n?.edgeResults?.get(p.id);if(b){if(d=p,s.push(p),p.entityConfig.dynamicAllocations)v={id:`${p.id}_dynamic_${b.allocationIndex}`,name:String(b.allocationIndex),bucketRange:[0,0],overrides:{}};else if(p.allocations[b.allocationIndex]&&(v=p.allocations[b.allocationIndex],u&&v))for(let[E,S]of Object.entries(v.overrides))E in i&&(i[E]=S);break}continue}else{let b=te(w,p.allocations);if(b){if(d=p,v=b,p.kind==="adaptive"){let[E,S]=b.bucketRange;C=(S-E+1)/r.hashing.bucketCount}if(s.push(p),u)for(let[E,S]of Object.entries(b.overrides))E in i&&(i[E]=S);break}}}}o.push({layerId:l.id,bucket:w,policyId:d?.id,policyKey:d?.key,allocationId:v?.id,allocationName:v?.name,allocationKey:v?.key,...C!==void 0&&C>0&&C<=1?{probability:C}:{},...O!==void 0?{modelVersion:O}:{},...y?{unitKey:g,unitKeyValue:x}:{},...u?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function ae(r,e,t,n){return qe(r,e,t,n).assignments}function ce(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=qe(r,e,t,n),c=Rt(e,a);return{decisionId:L(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:c,...r?.version?{configVersion:r.version}:{}}}}var P=class r{constructor(e={}){m(this,"_seen",new Map);m(this,"_ttlMs");m(this,"_maxEntries");m(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 $=class{constructor(e){m(this,"config");m(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 Ae(r,e,t,n,i){let o=[];for(let a of e){let c=t[a];if(c==null)return null;o.push(String(c))}let s=o.join("_");return{policyId:r,entityId:s,unitKeyValue:n,allocationCount:i,context:t}}var le=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 j="failed_events";var ue=class{constructor(e){this._queue=[];this._flushTimer=null;this._isFlushing=!1;this._isDisabled=!1;this._droppedCount=0;this._endpoint=e.endpoint,this._apiKey=e.apiKey,this._storage=e.storage,this._batchSize=e.batchSize??10,this._flushIntervalMs=e.flushIntervalMs??3e4,this._requestTimeoutMs=e.requestTimeoutMs??1e4,this._maxQueueSize=e.maxQueueSize??1e3,this._onError=e.onError,this._onSchemaWarnings=e.onSchemaWarnings,this._lifecycleProvider=e.lifecycleProvider,this._setupListeners(),this._retryFailedEvents(),this._startFlushTimer()}log(e){this._isDisabled||(this._queue.length>=this._maxQueueSize&&(this._queue.shift(),this._droppedCount++),this._queue.push(e),this._queue.length>=this._batchSize&&this.flush())}async flush(){if(this._isFlushing||this._isDisabled||this._queue.length===0)return;this._isFlushing=!0;let e=[...this._queue];this._queue=[];try{let t=await this._sendEvents(e);if(t>=200&&t<300)return;if(t===401){this._disable();return}if(t===429||t>=500){this._persistFailedEvents(e),this._onError?.(new Error(`HTTP ${t}: event delivery failed, will retry`));return}this._onError?.(new Error(`HTTP ${t}: batch rejected, dropping ${e.length} events`))}catch(t){this._persistFailedEvents(e),this._onError?.(t instanceof Error?t:new Error(String(t)))}finally{this._isFlushing=!1}}_disable(){this._isDisabled||(this._isDisabled=!0,this._queue=[],this._storage.remove(j),console.warn("[Traffical] API key rejected (HTTP 401); event delivery disabled for this client"))}get droppedCount(){return this._droppedCount}get isDisabled(){return this._isDisabled}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=new AbortController,n=setTimeout(()=>t.abort(),this._requestTimeoutMs),i;try{i=await fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e}),signal:t.signal})}finally{clearTimeout(n)}if(!i.ok)return i.status;if(this._onSchemaWarnings)try{let o=await i.json();o.schemaWarnings&&o.schemaWarnings.length>0&&this._onSchemaWarnings(o.schemaWarnings)}catch{}return i.status}_persistFailedEvents(e){let n=[...this._storage.get(j)??[],...e].slice(-100);this._storage.set(j,n)}_retryFailedEvents(){let e=this._storage.get(j);!e||e.length===0||(this._storage.remove(j),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 H="exposure_dedup";var W=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(H)}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(H)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(H,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(H);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(H);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var z="stable_id",Qt="traffical_sid";var de=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??Qt}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(z);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(z,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(z),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(z)!==null||this._getCookie()!==null}_persist(e){this._storage.set(z,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 G="traffical:",ke=class{constructor(){this._available=this._checkAvailability()}get(e){if(!this._available)return null;try{let t=localStorage.getItem(G+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(G+e,JSON.stringify(i))}catch{}}remove(e){if(this._available)try{localStorage.removeItem(G+e)}catch{}}clear(){if(this._available)try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n?.startsWith(G)&&e.push(n)}e.forEach(t=>localStorage.removeItem(t))}catch{}}_checkAvailability(){try{let e=G+"__test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}},De=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 Qe(){let r=new ke;return r.get("__check__")!==null||Yt()?r:new De}function Yt(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var D="0.16.2";var Zt="js-client";function Pe(r,e){let t=new P({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=P.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,configVersion:n.metadata.configVersion??e.getConfigVersion?.()??void 0,sdkName:Zt,sdkVersion:D};e.log(s)},onDestroy(){t.clear()}}}var en="traffical_rdr";function tn(r,e,t){if(!(typeof document>"u"))try{document.cookie=`${r}=${encodeURIComponent(e)}; max-age=${t}; path=/; SameSite=Lax`}catch{}}function Re(r={}){let e=r.parameterKey??"redirect.url",t=r.compareMode??"pathname",n=r.cookieName??en;return{name:"redirect",onInitialize(i){typeof window>"u"||i.decide({context:{},defaults:{[e]:""}})},onBeforeDecision(i){return typeof window>"u"?i:{"url.pathname":window.location.pathname,...i}},onDecision(i){let o=i.assignments[e];if(typeof o!="string"||!o)return;let s=t==="href"?window.location.href:window.location.pathname;if(o===s)return;let a=i.metadata.layers.find(c=>c.policyId&&c.allocationName);a&&tn(n,JSON.stringify({l:a.layerId,p:a.policyId,a:a.allocationName,ts:Date.now()}),86400),window.location.replace(o)}}}var nn="traffical_rdr";function rn(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 on(r,e){let t=rn(r);if(!t)return null;try{let n=JSON.parse(t);return Date.now()-n.ts>e?null:{layerId:n.l,policyId:n.p,allocationName:n.a}}catch{return null}}function Le(r={}){let e=r.cookieName??nn,t=r.expiryMs??864e5;function n(i){let o=on(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 fe=[],Ye={};function sn(){if(typeof window>"u")return{version:1,instances:Ye,subscribe:()=>()=>{}};if(!window.__TRAFFICAL_DEBUG__){let r={version:1,instances:Ye,subscribe(e){return fe.push(e),()=>{fe=fe.filter(t=>t!==e)}}};window.__TRAFFICAL_DEBUG__=r}return window.__TRAFFICAL_DEBUG__}function Ze(r){for(let e of fe)try{e(r)}catch{}}var an=0;function cn(){return`traffical_${Date.now().toString(36)}_${(++an).toString(36)}`}function ln(){return`evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}var un="traffical-debug";function Me(r={}){let e=r.instanceId??cn(),t=r.maxEvents??500,n=null,i=null,o={},s=[],a=null,c=null,f=[],h=[],l=[];function _(){return{ready:n?.isInitialized===!0,stableId:n?.getStableId?.()??null,effectiveUnitKey:c,configVersion:n?.getConfigVersion?.()??null,assignments:{...o},layers:[...s],lastDecisionId:a,overrides:n?.getOverrides?.()??{}}}function u(){let d=_();for(let v of h)try{v(d)}catch{}}function g(d,v){let C={id:ln(),type:d,timestamp:Date.now(),data:v};f.push(C),f.length>t&&f.splice(0,f.length-t);for(let O of l)try{O(C)}catch{}}function y(){if(n)try{n.decide({context:{},defaults:{}})}catch{}}let x={id:e,meta:{orgId:"",projectId:"",env:"",sdkVersion:D},getState:_,subscribe(d){return h.push(d),()=>{h=h.filter(v=>v!==d)}},getEvents(d){return d!==void 0?f.slice(-d):[...f]},onEvent(d){return l.push(d),()=>{l=l.filter(v=>v!==d)}},getConfigBundle(){return i},setUnitKey(d){n?.identify?n.identify(d):n?.setStableId&&n.setStableId(d),u()},setOverride(d,v){n?.applyOverrides&&n.applyOverrides({[d]:v}),u(),y()},clearOverride(d){if(n?.getOverrides&&n?.applyOverrides){let v=n.getOverrides();delete v[d],n.clearOverrides?.(),n.applyOverrides(v)}u(),y()},clearAllOverrides(){n?.clearOverrides?.(),u(),y()},getOverrides(){return n?.getOverrides?.()??{}},reDecide(){y()},async refresh(){n?.refreshConfig&&await n.refreshConfig()}};return{name:un,onInitialize(d){n=d,i&&(x.meta.orgId=i.orgId,x.meta.projectId=i.projectId,x.meta.env=i.env);let v=sn();v.instances[e]=x,Ze({type:"register",instanceId:e}),u()},onConfigUpdate(d){i=d,x.meta.orgId=d.orgId,x.meta.projectId=d.projectId,x.meta.env=d.env,u()},onDecision(d){o={...d.assignments},s=d.metadata?.layers?[...d.metadata.layers]:[],a=d.decisionId,d.metadata?.unitKeyValue&&(c=d.metadata.unitKeyValue),g("decision",d),u()},onResolve(d){o={...d},u()},onExposure(d){return g("exposure",d),!0},onTrack(d){return g("track",d),!0},onDestroy(){let d=typeof window<"u"?window.__TRAFFICAL_DEBUG__:null;d&&(delete d.instances[e],Ze({type:"unregister",instanceId:e})),h=[],l=[],n=null}}}var ge=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 et(){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 Oe="js-client";function tt(r,e){if(e!==void 0)return{context:r,defaults:e};let t=r;return{context:t.context,defaults:t.defaults}}var dn="https://sdk.traffical.io",fn=6e4,gn=1e4,hn=3e5,pn=3e5,mn=100,yn=.1;function vn(r){let e=r*yn;return r+(Math.random()*2-1)*e}function _n(r){if(!r||typeof r!="object")return!1;let e=r;if(!Array.isArray(e.parameters)||!Array.isArray(e.layers))return!1;let t=e.hashing;return!(!t||typeof t!="object"||typeof t.unitKey!="string"||t.unitKey.length===0||typeof t.bucketCount!="number"||!Number.isInteger(t.bucketCount)||t.bucketCount<1)}var M=class{constructor(e){this._state={bundle:null,etag:null,lastFetchTime:0,lastOfflineWarning:0,lastMalformedWarning:0,refreshTimer:null,isInitialized:!1,serverResponse:null,cachedEdgeResults:null};this._decisionCache=new Map;this._cumulativeAttribution=new Map;this._identityListeners=[];this._overrideListeners=[];this._overrides={};this._lastResolveContextKey=null;this._readyPromise=new Promise(e=>{this._readyResolve=e});let t=e.evaluationMode??"bundle";this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??dn,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??fn,attributionMode:e.attributionMode??"cumulative",evaluationMode:t},this._requestTimeoutMs=e.configTimeoutMs??e.requestTimeoutMs??gn;let n={baseUrl:this._options.baseUrl,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,apiKey:this._options.apiKey,defaultTimeoutMs:e.resolveTimeoutMs??e.requestTimeoutMs};if(this._decisionClient=new $(n),this._errorBoundary=new le(e.errorBoundary),this._storage=e.storage??Qe(),this._lifecycleProvider=e.lifecycleProvider??et(),!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 ue({endpoint:`${this._options.baseUrl}/v1/events/batch`,apiKey:e.apiKey,storage:this._storage,lifecycleProvider:this._lifecycleProvider,batchSize:e.batchSize??e.eventBatchSize,flushIntervalMs:e.flushIntervalMs??e.eventFlushIntervalMs,maxQueueSize:e.eventMaxQueueSize,requestTimeoutMs:e.eventsTimeoutMs??e.requestTimeoutMs,onError:i=>{console.warn("[Traffical] Event logging error:",i.message)},onSchemaWarnings:e.onSchemaWarnings}),this._exposureDedup=new W({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new de({storage:this._storage}),this._plugins=new ge,this._assignmentLogger=e.assignmentLogger,this._byoEventLogger=e.eventLogger,this._disableCloudEvents=e.disableCloudEvents??!1,this._assignmentLoggerDedup=e.deduplicateAssignmentLogger!==!1&&e.assignmentLogger?new W({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}):null,e.trackDecisions!==!1&&(!this._disableCloudEvents||this._byoEventLogger)&&this._plugins.register({plugin:Pe({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:i=>this._dispatchEvent(i),getConfigVersion:()=>this.getConfigVersion()}),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),this._readyResolve()}get isInitialized(){return this._state.isInitialized}async waitForReady(){return this._readyPromise}async close(){if(this._state.refreshTimer&&(clearInterval(this._state.refreshTimer),this._state.refreshTimer=null),this._lifecycleProvider.isUnloading()?this._eventLogger.flushBeacon():await 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)}}}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}getUnitKeyField(){return oe(this._getEffectiveBundle())}getParameterLayerId(e){return se(this._getEffectiveBundle(),e)}getParams(e,t){let{context:n,defaults:i}=tt(e,t);return this._errorBoundary.capture("getParams",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){this._maybeResolveForContext(n);let c={...i};for(let[f,h]of Object.entries(this._state.serverResponse.assignments))f in c&&(c[f]=h);return this._plugins.runResolve(c),this._applyOverridesToResult(c),c}let o=this._getEffectiveBundle(),s=this._enrichContext(n),a=ae(o,s,i);return this._plugins.runResolve(a),this._applyOverridesToResult(a),a},i)}decide(e,t){let{context:n,defaults:i}=tt(e,t);return this._errorBoundary.capture("decide",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){this._maybeResolveForContext(n);let f=this._state.serverResponse,h={...i};for(let[_,u]of Object.entries(f.assignments))_ in h&&(h[_]=u);let l={decisionId:L(),assignments:h,metadata:{...f.metadata,configVersion:f.stateVersion}};return this._cacheDecision(l),this._updateCumulativeAttribution(l),this._plugins.runDecision(l),this._applyOverridesToResult(l.assignments),this._emitAssignmentLogEntries(l,"decision"),l}let o=this._getEffectiveBundle(),s=this._enrichContext(n);s=this._plugins.runBeforeDecision(s);let a=this._state.cachedEdgeResults??void 0,c=ce(o,s,i,a);return this._cacheDecision(c),this._updateCumulativeAttribution(c),this._plugins.runDecision(c),this._applyOverridesToResult(c.assignments),this._emitAssignmentLogEntries(c,"decision"),c},{decisionId:L(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:"",layers:[]}})}trackExposure(e){this._errorBoundary.capture("trackExposure",()=>{let t=e.metadata.unitKeyValue;if(!t)return;this._emitAssignmentLogEntries(e,"exposure");let n=e.metadata.configVersion??this.getConfigVersion()??void 0,i=[];for(let s of e.metadata.layers)!s.policyId||!s.allocationName||s.attributionOnly||!this._exposureDedup.checkAndMark(t,s.policyId,s.allocationName)||i.push(s);if(i.length===0)return;let o={type:"exposure",id:we(),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:i,context:e.metadata.filteredContext,configVersion:n,sdkName:Oe,sdkVersion:D};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 n?.value=="number"?n.value:typeof t?.value=="number"?t.value:void 0,s=this._buildAttribution(i,n?.decisionId),a=n?.decisionId,c={type:"track",id:Ce(),orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:i,timestamp:new Date().toISOString(),event:e,value:o,values:n?.values,properties:t,decisionId:a,attribution:s,eventTimestamp:n?.eventTimestamp,sdkName:Oe,sdkVersion:D};this._plugins.runTrack(c)&&this._dispatchEvent(c)},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)return;let i=e.metadata.configVersion??this.getConfigVersion()??void 0;for(let o of e.metadata.layers)!o.policyId||!o.allocationName||this._assignmentLoggerDedup&&!this._assignmentLoggerDedup.checkAndMark(n,o.policyId,`${o.allocationName}:${t}`)||this._assignmentLogger({unitKey:n,policyId:o.policyId,policyKey:o.policyKey,allocationName:o.allocationName,allocationKey:o.allocationKey,timestamp:e.metadata.timestamp,layerId:o.layerId,allocationId:o.allocationId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,sdkName:Oe,sdkVersion:D,properties:e.metadata.filteredContext,type:t,decisionId:e.decisionId,anonymousId:this._stableId.getId(),id:Se(),bucket:o.bucket>=0?o.bucket:void 0,probability:o.probability,modelVersion:o.modelVersion,configVersion:i})}_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/${encodeURIComponent(this._options.projectId)}?env=${encodeURIComponent(this._options.env)}`,t={"Content-Type":"application/json",Authorization:`Bearer ${this._options.apiKey}`};this._state.etag&&(t["If-None-Match"]=this._state.etag);let n=new AbortController,i=setTimeout(()=>n.abort(),this._requestTimeoutMs);try{let o=await fetch(e,{method:"GET",headers:t,signal:n.signal});if(o.status===304){this._state.lastFetchTime=Date.now();return}if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);let s=await o.json(),a=o.headers.get("ETag");if(!_n(s)){this._logMalformedBundleWarning();return}if(this._state.bundle=s,this._state.etag=a,this._state.lastFetchTime=Date.now(),this._findEdgePolicies(s).length>0){let c=await this._prefetchEdgeResults(s,this._enrichContext({}));this._state.cachedEdgeResults=c}else this._state.cachedEdgeResults=null;this._plugins.runConfigUpdate(s)}catch(o){this._logOfflineWarning(o)}finally{clearTimeout(i)}}_startBackgroundRefresh(){let e=this._options.evaluationMode==="server"?this._state.serverResponse?.suggestedRefreshMs??this._options.refreshIntervalMs:this._options.refreshIntervalMs;if(e<=0)return;let t=()=>{this._state.refreshTimer=setTimeout(()=>{t(),this._options.evaluationMode==="server"?this._fetchServerResolve().catch(()=>{}):this._fetchConfig().catch(()=>{})},vn(e))};t()}_maybeResolveForContext(e){let t=this._enrichContext(e),n;try{n=JSON.stringify(t)}catch{n=""}n!==this._lastResolveContextKey&&(this._lastResolveContextKey=n,this._fetchServerResolve(t))}async _fetchServerResolve(e){if(this._decisionClient)try{let t=e??this._enrichContext({}),n=await this._decisionClient.resolve({context:t});n&&(this._state.serverResponse=n,this._state.lastFetchTime=Date.now())}catch(t){this._logOfflineWarning(t)}}_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=K(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 Ae(s.id,s.entityConfig.entityKeys,t,i,a||void 0)}).filter(s=>s!==null);if(o.length===0)return{};try{let s=await this._decisionClient.decideEntityBatch(o),a=new Map;for(let c=0;c<o.length;c++){let f=s[c];f&&a.set(o[c].policyId,{allocationIndex:f.allocationIndex,entityId:o[c].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>hn&&(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)}_logMalformedBundleWarning(){let e=Date.now();e-this._state.lastMalformedWarning>pn&&(console.warn(`[Traffical] Discarded malformed config bundle (invalid hashing/shape). Using ${this._state.bundle?"cached":"local"} config.`),this._state.lastMalformedWarning=e)}_cacheDecision(e){if(this._decisionCache.size>=mn){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 nt(r){let e=new M(r);return await e.initialize(),e}function it(r){return new M(r)}function rt(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(u,g){try{return new RegExp(u).test(g)}catch{return g===u}}function a(u,g,y){if(g==="innerHTML")u.innerHTML=y;else if(g==="textContent")u.textContent=y;else if(g==="src"&&"src"in u)u.src=y;else if(g==="href"&&"href"in u)u.href=y;else if(g.startsWith("style.")){let x=g.slice(6);u.style[x]=y}else u.setAttribute(g,y)}function c(u,g){let y=String(g);try{let x=document.querySelectorAll(u.selector);for(let w of x)a(w,u.property,y)}catch(x){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${u.parameterKey}:`,x)}}function f(u,g=!1){n=u;let y=typeof window<"u"?window.location.pathname:"";for(let x of t){if(!g&&!s(x.urlPattern,y))continue;let w=u[x.parameterKey];w!==void 0&&c(x,w)}}function h(){o&&clearTimeout(o),o=setTimeout(()=>{f(n)},e.debounceMs)}function l(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{h()}),i.observe(document.body,{childList:!0,subtree:!0}))}function _(){i&&(i.disconnect(),i=null),o&&(clearTimeout(o),o=null)}return{name:"dom-binding",onInitialize(){e.observeMutations&&l()},onConfigUpdate(u){t=u.domBindings??[]},onResolve(u){f(u)},onDecision(u){f(u.assignments)},onDestroy(){_(),t=[],n={}},applyBindings(u){f(u||n)},getBindings(){return t}}}var T=null;async function xn(r){return T?(console.warn("[Traffical] Client already initialized. Returning existing instance."),T):(T=await nt(r),T)}function bn(r){return T?(console.warn("[Traffical] Client already initialized. Returning existing instance."),T):(T=it(r),T.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),T)}function En(){return T}function Tn(){T&&(T.destroy(),T=null)}return ft(In);})();
|
|
3
3
|
//# sourceMappingURL=traffical.min.js.map
|