@traffical/js-client 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,13 +45,13 @@ export class PluginManager {
45
45
  return this._plugins.map((p) => p.plugin);
46
46
  }
47
47
  /**
48
- * Run onInitialize hooks.
48
+ * Run onInitialize hooks, passing the client API reference.
49
49
  */
50
- async runInitialize() {
50
+ async runInitialize(client) {
51
51
  for (const { plugin } of this._plugins) {
52
52
  if (plugin.onInitialize) {
53
53
  try {
54
- await plugin.onInitialize();
54
+ await plugin.onInitialize(client);
55
55
  }
56
56
  catch (error) {
57
57
  console.warn(`[Traffical] Plugin "${plugin.name}" onInitialize error:`, error);
@@ -191,4 +191,6 @@ export class PluginManager {
191
191
  }
192
192
  // Re-export plugins
193
193
  export { createDecisionTrackingPlugin, } from "./decision-tracking.js";
194
+ export { createRedirectPlugin, } from "./redirect.js";
195
+ export { createRedirectAttributionPlugin, } from "./redirect-attribution.js";
194
196
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { TrafficalPlugin } from "./types.js";
2
+ export interface RedirectAttributionPluginOptions {
3
+ /** Cookie name to read attribution from. Default: "traffical_rdr" */
4
+ cookieName?: string;
5
+ /** How long the attribution cookie is valid in ms. Default: 24 hours */
6
+ expiryMs?: number;
7
+ }
8
+ export declare function createRedirectAttributionPlugin(options?: RedirectAttributionPluginOptions): TrafficalPlugin;
9
+ //# sourceMappingURL=redirect-attribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-attribution.d.ts","sourceRoot":"","sources":["../../src/plugins/redirect-attribution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMlD,MAAM,WAAW,gCAAgC;IAC/C,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA0CD,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,gCAAqC,GAC7C,eAAe,CA6BjB"}
@@ -0,0 +1,61 @@
1
+ const COOKIE_NAME = "traffical_rdr";
2
+ const DEFAULT_EXPIRY_MS = 24 * 60 * 60 * 1000; // 24 hours
3
+ function readCookie(name) {
4
+ if (typeof document === "undefined")
5
+ return null;
6
+ try {
7
+ for (const part of document.cookie.split(";")) {
8
+ const [k, v] = part.trim().split("=");
9
+ if (k === name && v)
10
+ return decodeURIComponent(v);
11
+ }
12
+ }
13
+ catch {
14
+ // cookie access failed
15
+ }
16
+ return null;
17
+ }
18
+ function parseAttribution(cookieName, expiryMs) {
19
+ const raw = readCookie(cookieName);
20
+ if (!raw)
21
+ return null;
22
+ try {
23
+ const data = JSON.parse(raw);
24
+ if (Date.now() - data.ts > expiryMs)
25
+ return null;
26
+ return {
27
+ layerId: data.l,
28
+ policyId: data.p,
29
+ allocationName: data.a,
30
+ };
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ export function createRedirectAttributionPlugin(options = {}) {
37
+ const cookieName = options.cookieName ?? COOKIE_NAME;
38
+ const expiryMs = options.expiryMs ?? DEFAULT_EXPIRY_MS;
39
+ function inject(event) {
40
+ const attr = parseAttribution(cookieName, expiryMs);
41
+ if (!attr)
42
+ return;
43
+ event.attribution = event.attribution ?? [];
44
+ const already = event.attribution.some((a) => a.layerId === attr.layerId && a.policyId === attr.policyId);
45
+ if (!already) {
46
+ event.attribution.push(attr);
47
+ }
48
+ }
49
+ return {
50
+ name: "redirect-attribution",
51
+ onTrack(event) {
52
+ inject(event);
53
+ return true;
54
+ },
55
+ onExposure(event) {
56
+ inject(event);
57
+ return true;
58
+ },
59
+ };
60
+ }
61
+ //# sourceMappingURL=redirect-attribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-attribution.js","sourceRoot":"","sources":["../../src/plugins/redirect-attribution.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,GAAG,eAAe,CAAC;AACpC,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAgB1D,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;gBAAE,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CACvB,UAAkB,EAClB,QAAgB;IAEhB,MAAM,GAAG,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,IAAI,GAAsB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,QAAQ;YAAE,OAAO,IAAI,CAAC;QACjD,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,CAAC;YACf,QAAQ,EAAE,IAAI,CAAC,CAAC;YAChB,cAAc,EAAE,IAAI,CAAC,CAAC;SACvB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,UAA4C,EAAE;IAE9C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,WAAW,CAAC;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,iBAAiB,CAAC;IAEvD,SAAS,MAAM,CAAC,KAA2C;QACzD,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAClE,CAAC;QACF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,sBAAsB;QAE5B,OAAO,CAAC,KAAiB;YACvB,MAAM,CAAC,KAAK,CAAC,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,UAAU,CAAC,KAAoB;YAC7B,MAAM,CAAC,KAAwD,CAAC,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { TrafficalPlugin } from "./types.js";
2
+ export interface RedirectPluginOptions {
3
+ /** Parameter key to check for a redirect URL. Default: "redirect.url" */
4
+ parameterKey?: string;
5
+ /** How to compare the resolved URL with the current location.
6
+ * "pathname" compares against window.location.pathname (default).
7
+ * "href" compares against the full window.location.href. */
8
+ compareMode?: "pathname" | "href";
9
+ /** Cookie name for redirect attribution. Default: "traffical_rdr" */
10
+ cookieName?: string;
11
+ }
12
+ export declare function createRedirectPlugin(options?: RedirectPluginOptions): TrafficalPlugin;
13
+ //# sourceMappingURL=redirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/plugins/redirect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,YAAY,CAAC;AAMnE,MAAM,WAAW,qBAAqB;IACpC,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;iEAE6D;IAC7D,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAClC,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,qBAA0B,GAClC,eAAe,CAuDjB"}
@@ -0,0 +1,57 @@
1
+ const RDR_COOKIE = "traffical_rdr";
2
+ const RDR_MAX_AGE = 24 * 60 * 60; // 24 hours in seconds
3
+ function setCookie(name, value, maxAge) {
4
+ if (typeof document === "undefined")
5
+ return;
6
+ try {
7
+ document.cookie = `${name}=${encodeURIComponent(value)}; max-age=${maxAge}; path=/; SameSite=Lax`;
8
+ }
9
+ catch {
10
+ // cookie access may fail
11
+ }
12
+ }
13
+ export function createRedirectPlugin(options = {}) {
14
+ const parameterKey = options.parameterKey ?? "redirect.url";
15
+ const compareMode = options.compareMode ?? "pathname";
16
+ const cookieName = options.cookieName ?? RDR_COOKIE;
17
+ return {
18
+ name: "redirect",
19
+ onInitialize(client) {
20
+ if (typeof window === "undefined")
21
+ return;
22
+ client.decide({
23
+ context: {},
24
+ defaults: { [parameterKey]: "" },
25
+ });
26
+ },
27
+ onBeforeDecision(context) {
28
+ if (typeof window === "undefined")
29
+ return context;
30
+ return {
31
+ "url.pathname": window.location.pathname,
32
+ ...context,
33
+ };
34
+ },
35
+ onDecision(decision) {
36
+ const url = decision.assignments[parameterKey];
37
+ if (typeof url !== "string" || !url)
38
+ return;
39
+ const current = compareMode === "href"
40
+ ? window.location.href
41
+ : window.location.pathname;
42
+ if (url === current)
43
+ return;
44
+ const layer = decision.metadata.layers.find((l) => l.policyId && l.allocationName);
45
+ if (layer) {
46
+ setCookie(cookieName, JSON.stringify({
47
+ l: layer.layerId,
48
+ p: layer.policyId,
49
+ a: layer.allocationName,
50
+ ts: Date.now(),
51
+ }), RDR_MAX_AGE);
52
+ }
53
+ window.location.replace(url);
54
+ },
55
+ };
56
+ }
57
+ //# sourceMappingURL=redirect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect.js","sourceRoot":"","sources":["../../src/plugins/redirect.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,GAAG,eAAe,CAAC;AACnC,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,sBAAsB;AAaxD,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa,EAAE,MAAc;IAC5D,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO;IAC5C,IAAI,CAAC;QACH,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,IAAI,kBAAkB,CAAC,KAAK,CAAC,aAAa,MAAM,wBAAwB,CAAC;IACpG,CAAC;IAAC,MAAM,CAAC;QACP,yBAAyB;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,UAAiC,EAAE;IAEnC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,cAAc,CAAC;IAC5D,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,UAAU,CAAC;IACtD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC;IAEpD,OAAO;QACL,IAAI,EAAE,UAAU;QAEhB,YAAY,CAAC,MAAuB;YAClC,IAAI,OAAO,MAAM,KAAK,WAAW;gBAAE,OAAO;YAE1C,MAAM,CAAC,MAAM,CAAC;gBACZ,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;QAED,gBAAgB,CAAC,OAAgB;YAC/B,IAAI,OAAO,MAAM,KAAK,WAAW;gBAAE,OAAO,OAAO,CAAC;YAClD,OAAO;gBACL,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;gBACxC,GAAG,OAAO;aACX,CAAC;QACJ,CAAC;QAED,UAAU,CAAC,QAAwB;YACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YAC/C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG;gBAAE,OAAO;YAE5C,MAAM,OAAO,GACX,WAAW,KAAK,MAAM;gBACpB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI;gBACtB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAE/B,IAAI,GAAG,KAAK,OAAO;gBAAE,OAAO;YAE5B,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CACzC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,cAAc,CACtC,CAAC;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,SAAS,CACP,UAAU,EACV,IAAI,CAAC,SAAS,CAAC;oBACb,CAAC,EAAE,KAAK,CAAC,OAAO;oBAChB,CAAC,EAAE,KAAK,CAAC,QAAQ;oBACjB,CAAC,EAAE,KAAK,CAAC,cAAc;oBACvB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;iBACf,CAAC,EACF,WAAW,CACZ,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -4,6 +4,25 @@
4
4
  * Plugins can hook into various SDK lifecycle events.
5
5
  */
6
6
  import type { ConfigBundle, DecisionResult, ExposureEvent, TrackEvent, Context, ParameterValue } from "@traffical/core";
7
+ /**
8
+ * Minimal client interface exposed to plugins.
9
+ * Avoids circular dependency with the full TrafficalClient class.
10
+ */
11
+ export interface PluginClientAPI {
12
+ decide<T extends Record<string, ParameterValue>>(options: {
13
+ context: Context;
14
+ defaults: T;
15
+ }): DecisionResult;
16
+ getParams<T extends Record<string, ParameterValue>>(options: {
17
+ context: Context;
18
+ defaults: T;
19
+ }): T;
20
+ track(eventName: string, properties?: Record<string, unknown>, options?: {
21
+ decisionId?: string;
22
+ unitKey?: string;
23
+ }): void;
24
+ trackExposure(decision: DecisionResult): void;
25
+ }
7
26
  /**
8
27
  * Plugin interface - implement any subset of hooks.
9
28
  */
@@ -12,8 +31,10 @@ export interface TrafficalPlugin {
12
31
  name: string;
13
32
  /**
14
33
  * Called after client initialization completes.
34
+ * Receives a reference to the client API for plugins that need
35
+ * to trigger decisions or track events autonomously.
15
36
  */
16
- onInitialize?: () => void | Promise<void>;
37
+ onInitialize?: (client: PluginClientAPI) => void | Promise<void>;
17
38
  /**
18
39
  * Called when the config bundle is fetched or refreshed.
19
40
  * Useful for plugins that need access to bundle data (e.g., DOM bindings).
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,OAAO,EACP,cAAc,EACf,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAEhD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,CAAC;IAExD;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;IAEhD;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,IAAI,CAAC;IAE7D;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,GAAG,IAAI,CAAC;IAEtD;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,GAAG,IAAI,CAAC;IAEhD;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,OAAO,EACP,cAAc,EACf,MAAM,iBAAiB,CAAC;AAEzB;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAC7C,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,CAAC,CAAA;KAAE,GACzC,cAAc,CAAC;IAClB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAChD,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,CAAC,CAAA;KAAE,GACzC,CAAC,CAAC;IACL,KAAK,CACH,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAClD,IAAI,CAAC;IACR,aAAa,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAEhD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,CAAC;IAExD;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;IAEhD;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,IAAI,CAAC;IAE7D;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,GAAG,IAAI,CAAC;IAEtD;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,GAAG,IAAI,CAAC;IAEhD;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -1,3 +1,3 @@
1
- /* @traffical/js-client v0.3.0 */
2
- "use strict";var Traffical=(()=>{var R=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var _e=Object.prototype.hasOwnProperty;var me=(r,e,t)=>e in r?R(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var ve=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ye=(r,e)=>{for(var t in e)R(r,t,{get:e[t],enumerable:!0})},Te=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of pe(e))!_e.call(r,i)&&i!==t&&R(r,i,{get:()=>e[i],enumerable:!(n=he(e,i))||n.enumerable});return r};var Ee=r=>Te(R({},"__esModule",{value:!0}),r);var E=(r,e,t)=>(me(r,typeof e!="symbol"?e+"":e,t),t);var ie=ve(()=>{});var gt={};ye(gt,{TrafficalClient:()=>b,createDOMBindingPlugin:()=>ge,destroy:()=>ft,init:()=>ct,initSync:()=>ut,instance:()=>dt});function x(r){let e=2166136261;for(let t=0;t<r.length;t++)e^=r.charCodeAt(t),e=Math.imul(e,16777619);return e>>>0}function O(r,e,t){let n=`${r}:${e}`;return x(n)%t}function q(r,e){return r>=e[0]&&r<=e[1]}function B(r,e){for(let t of e)if(q(r,t.bucketRange))return t;return null}function X(r,e){let{field:t,op:n,value:i,values:o}=r,s=be(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 N(r,e){return r.length===0?!0:r.every(t=>X(t,e))}function be(r,e){let t=e.split("."),n=r;for(let i of t){if(n==null)return;if(typeof n=="object")n=n[i];else return}return n}var we=r=>crypto.getRandomValues(new Uint8Array(r)),Ce=(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}}},ne=(r,e=21)=>Ce(r,e|0,we);function K(r){let e=new Error(r);return e.source="ulid",e}var G="0123456789ABCDEFGHJKMNPQRSTVWXYZ",C=G.length,re=Math.pow(2,48)-1,Se=10,ke=16;function De(r){let e=Math.floor(r()*C);return e===C&&(e=C-1),G.charAt(e)}function Me(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>re)throw K("cannot encode time greater than "+re);if(r<0)throw K("time must be positive");if(Number.isInteger(Number(r))===!1)throw K("time must be an integer");let t,n="";for(;e>0;e--)t=r%C,n=G.charAt(t)+n,r=(r-t)/C;return n}function Pe(r,e){let t="";for(;r>0;r--)t=De(e)+t;return t}function Ae(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=ie();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 K("secure crypto unusable, insecure Math.random not allowed")}function Re(r){return r||(r=Ae()),function(t){return isNaN(t)&&(t=Date.now()),Me(t,Se)+Pe(ke,r)}}var oe=Re();var Oe="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Be=8,kt=ne(Oe,Be);function L(r){return`${r}_${oe()}`}function S(){return L("dec")}function J(){return L("exp")}function Y(){return L("trk")}function Ne(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 Ke(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 Le(r,e){if(r.length===0||r.length===1)return 0;let n=x(e)%1e4/1e4,i=0;for(let o=0;o<r.length;o++)if(i+=r[o],n<i)return o;return r.length-1}function se(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function $e(r,e,t,n){let i=r.entityState?.[e];if(!i)return se(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:se(n)}function Ve(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=Ke(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let f=i.dynamicAllocations.countKey,v=t[f];if(typeof v!="number"||v<=0)return null;a=Math.floor(v),s=Array.from({length:a},(l,d)=>({id:`${e.id}_dynamic_${d}`,name:String(d),bucketRange:[0,0],overrides:{}}))}else s=e.allocations,a=s.length;if(a===0)return null;let c=$e(r,e.id,o,a),h=`${o}:${n}:${e.id}`,T=Le(c,h);return{allocation:s[T],entityId:o}}function k(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function ae(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=k(r,e);if(!a)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let c=new Set(Object.keys(t)),h=r.parameters.filter(f=>c.has(f.key));for(let f of h)f.key in i&&(i[f.key]=f.default);let T=new Map;for(let f of h){let v=T.get(f.layerId)||[];v.push(f),T.set(f.layerId,v)}for(let f of r.layers){let v=T.get(f.id),l=v&&v.length>0,d=O(a,f.id,r.hashing.bucketCount),p,g;for(let u of f.policies)if(u.state==="running"){if(u.eligibleBucketRange){let{start:_,end:y}=u.eligibleBucketRange;if(d<_||d>y)continue}if(N(u.conditions,e))if(u.entityConfig&&u.entityConfig.resolutionMode==="bundle"){let _=Ve(r,u,e,a);if(_){if(p=u,g=_.allocation,s.push(u),l&&!u.entityConfig.dynamicAllocations)for(let[y,w]of Object.entries(_.allocation.overrides))y in i&&(i[y]=w);break}}else if(u.entityConfig&&u.entityConfig.resolutionMode==="edge"){let _=n?.edgeResults?.get(u.id);if(_){if(p=u,s.push(u),u.entityConfig.dynamicAllocations)g={id:`${u.id}_dynamic_${_.allocationIndex}`,name:String(_.allocationIndex),bucketRange:[0,0],overrides:{}};else if(u.allocations[_.allocationIndex]&&(g=u.allocations[_.allocationIndex],l&&g))for(let[y,w]of Object.entries(g.overrides))y in i&&(i[y]=w);break}continue}else{let _=B(d,u.allocations);if(_){if(p=u,g=_,s.push(u),l)for(let[y,w]of Object.entries(_.overrides))y in i&&(i[y]=w);break}}}o.push({layerId:f.id,bucket:d,policyId:p?.id,allocationId:g?.id,allocationName:g?.name,...l?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function $(r,e,t,n){return ae(r,e,t,n).assignments}function V(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=ae(r,e,t,n),c=Ne(e,a);return{decisionId:S(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:c}}}var I=class r{constructor(e={}){E(this,"_seen",new Map);E(this,"_ttlMs");E(this,"_maxEntries");E(this,"_lastCleanup",Date.now());this._ttlMs=e.ttlMs??36e5,this._maxEntries=e.maxEntries??1e4}static hashAssignments(e){let t=Object.keys(e).sort(),n=[];for(let i of t){let o=e[i],s=typeof o=="object"?JSON.stringify(o):String(o);n.push(`${i}=${s}`)}return n.join("|")}static createKey(e,t){return`${e}:${t}`}checkAndMark(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o!==void 0&&i-o<this._ttlMs?!1:(this._seen.set(n,i),this._maybeCleanup(i),!0)}wouldBeNew(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o===void 0?!0:i-o>=this._ttlMs}clear(){this._seen.clear()}get size(){return this._seen.size}_maybeCleanup(e){(e-this._lastCleanup>this._ttlMs*.2||this._seen.size>this._maxEntries)&&(this._lastCleanup=e,this._cleanup(e))}_cleanup(e){let t=[];for(let[n,i]of this._seen.entries())e-i>=this._ttlMs&&t.push(n);for(let n of t)this._seen.delete(n);if(this._seen.size>this._maxEntries){let i=Array.from(this._seen.entries()).sort((o,s)=>o[1]-s[1]).slice(0,this._seen.size-this._maxEntries);for(let[o]of i)this._seen.delete(o)}}};var D=class{constructor(e){E(this,"config");E(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 Z(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 F=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 U="failed_events";var j=class{constructor(e){this._queue=[];this._flushTimer=null;this._isFlushing=!1;this._onPageHide=()=>{this.flushBeacon()};this._onVisibilityChange=()=>{document.visibilityState==="hidden"&&this.flushBeacon()};this._onBeforeUnload=()=>{this.flushBeacon()};this._endpoint=e.endpoint,this._apiKey=e.apiKey,this._storage=e.storage,this._batchSize=e.batchSize??10,this._flushIntervalMs=e.flushIntervalMs??3e4,this._onError=e.onError,this._setupListeners(),this._retryFailedEvents(),this._startFlushTimer()}log(e){this._queue.push(e),this._queue.length>=this._batchSize&&this.flush()}async flush(){if(this._isFlushing||this._queue.length===0)return;this._isFlushing=!0;let e=[...this._queue];this._queue=[];try{await this._sendEvents(e)}catch(t){this._persistFailedEvents(e),this._onError?.(t instanceof Error?t:new Error(String(t)))}finally{this._isFlushing=!1}}flushBeacon(){if(this._queue.length===0)return!0;if(typeof fetch>"u")return this.flush(),!1;let e=[...this._queue];return this._queue=[],fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e}),keepalive:!0}).catch(()=>{this._persistFailedEvents(e)}),!0}get queueSize(){return this._queue.length}destroy(){this._flushTimer&&(clearInterval(this._flushTimer),this._flushTimer=null),this._removeListeners()}async _sendEvents(e){let t=await fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e})});if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`)}_persistFailedEvents(e){let n=[...this._storage.get(U)??[],...e].slice(-100);this._storage.set(U,n)}_retryFailedEvents(){let e=this._storage.get(U);!e||e.length===0||(this._storage.remove(U),this._queue.push(...e))}_startFlushTimer(){this._flushIntervalMs<=0||(this._flushTimer=setInterval(()=>{this.flush().catch(()=>{})},this._flushIntervalMs))}_setupListeners(){typeof window>"u"||(window.addEventListener("pagehide",this._onPageHide),document.addEventListener("visibilitychange",this._onVisibilityChange),window.addEventListener("beforeunload",this._onBeforeUnload))}_removeListeners(){typeof window>"u"||(window.removeEventListener("pagehide",this._onPageHide),document.removeEventListener("visibilitychange",this._onVisibilityChange),window.removeEventListener("beforeunload",this._onBeforeUnload))}};var M="exposure_dedup";var z=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(M)}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(M)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(M,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(M);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(M);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var P="stable_id",tt="traffical_sid";var W=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??tt}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(P);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(P,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(P),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(P)!==null||this._getCookie()!==null}_persist(e){this._storage.set(P,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 A="traffical:",Q=class{constructor(){this._available=this._checkAvailability()}get(e){if(!this._available)return null;try{let t=localStorage.getItem(A+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(A+e,JSON.stringify(i))}catch{}}remove(e){if(this._available)try{localStorage.removeItem(A+e)}catch{}}clear(){if(this._available)try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n?.startsWith(A)&&e.push(n)}e.forEach(t=>localStorage.removeItem(t))}catch{}}_checkAvailability(){try{let e=A+"__test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}},ee=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 le(){let r=new Q;return r.get("__check__")!==null||nt()?r:new ee}function nt(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var it="js-client",rt="0.1.0";function te(r,e){let t=new I({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=I.hashAssignments(n.assignments);if(!t.checkAndMark(i,o))return;let s={type:"decision",id:n.decisionId,orgId:e.orgId,projectId:e.projectId,env:e.env,unitKey:i,timestamp:n.metadata.timestamp,assignments:n.assignments,layers:n.metadata.layers,context:n.metadata.filteredContext,sdkName:it,sdkVersion:rt};e.log(s)},onDestroy(){t.clear()}}}var H=class{constructor(){this._plugins=[]}register(e){let t="plugin"in e?e.plugin:e,n="priority"in e?e.priority??0:0;if(this._plugins.some(i=>i.plugin.name===t.name)){console.warn(`[Traffical] Plugin "${t.name}" already registered, skipping.`);return}this._plugins.push({plugin:t,priority:n}),this._plugins.sort((i,o)=>o.priority-i.priority)}unregister(e){let t=this._plugins.findIndex(n=>n.plugin.name===e);return t===-1?!1:(this._plugins.splice(t,1),!0)}get(e){return this._plugins.find(t=>t.plugin.name===e)?.plugin}getAll(){return this._plugins.map(e=>e.plugin)}async runInitialize(){for(let{plugin:e}of this._plugins)if(e.onInitialize)try{await e.onInitialize()}catch(t){console.warn(`[Traffical] Plugin "${e.name}" onInitialize error:`,t)}}runConfigUpdate(e){for(let{plugin:t}of this._plugins)if(t.onConfigUpdate)try{t.onConfigUpdate(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onConfigUpdate error:`,n)}}runBeforeDecision(e){let t=e;for(let{plugin:n}of this._plugins)if(n.onBeforeDecision)try{let i=n.onBeforeDecision(t);i&&(t=i)}catch(i){console.warn(`[Traffical] Plugin "${n.name}" onBeforeDecision error:`,i)}return t}runDecision(e){for(let{plugin:t}of this._plugins)if(t.onDecision)try{t.onDecision(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onDecision error:`,n)}}runResolve(e){for(let{plugin:t}of this._plugins)if(t.onResolve)try{t.onResolve(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onResolve error:`,n)}}runExposure(e){for(let{plugin:t}of this._plugins)if(t.onExposure)try{if(t.onExposure(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onExposure error:`,n)}return!0}runTrack(e){for(let{plugin:t}of this._plugins)if(t.onTrack)try{if(t.onTrack(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onTrack error:`,n)}return!0}runDestroy(){for(let{plugin:e}of this._plugins)if(e.onDestroy)try{e.onDestroy()}catch(t){console.warn(`[Traffical] Plugin "${e.name}" onDestroy error:`,t)}}clear(){this._plugins=[]}};var ce="js-client",ue="0.1.0",ot="https://sdk.traffical.io",st=6e4,at=3e5,lt=100,b=class{constructor(e){this._state={bundle:null,etag:null,lastFetchTime:0,lastOfflineWarning:0,refreshTimer:null,isInitialized:!1,serverResponse:null,cachedEdgeResults:null};this._decisionCache=new Map;this._cumulativeAttribution=new Map;let t=e.evaluationMode??"bundle";this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??ot,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??st,attributionMode:e.attributionMode??"cumulative",evaluationMode:t};let n={baseUrl:this._options.baseUrl,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,apiKey:this._options.apiKey};if(this._decisionClient=new D(n),this._errorBoundary=new F(e.errorBoundary),this._storage=e.storage??le(),this._eventLogger=new j({endpoint:`${this._options.baseUrl}/v1/events/batch`,apiKey:e.apiKey,storage:this._storage,batchSize:e.eventBatchSize,flushIntervalMs:e.eventFlushIntervalMs,onError:i=>{console.warn("[Traffical] Event logging error:",i.message)}}),this._exposureDedup=new z({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new W({storage:this._storage}),this._plugins=new H,e.trackDecisions!==!1&&this._plugins.register({plugin:te({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:i=>this._eventLogger.log(i)}),priority:100}),e.plugins)for(let i of e.plugins)this._plugins.register(i);this._options.localConfig&&(this._state.bundle=this._options.localConfig,this._plugins.runConfigUpdate(this._options.localConfig))}async initialize(){await this._errorBoundary.captureAsync("initialize",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig(),this._startBackgroundRefresh(),this._state.isInitialized=!0,await this._plugins.runInitialize()},void 0)}get isInitialized(){return this._state.isInitialized}destroy(){this._state.refreshTimer&&(clearInterval(this._state.refreshTimer),this._state.refreshTimer=null),this._eventLogger.flushBeacon(),this._eventLogger.destroy(),this._plugins.runDestroy()}async refreshConfig(){await this._errorBoundary.swallow("refreshConfig",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig()})}getConfigVersion(){return this._state.serverResponse?.stateVersion??this._state.bundle?.version??null}getParams(e){return this._errorBoundary.capture("getParams",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let o={...e.defaults};for(let[s,a]of Object.entries(this._state.serverResponse.assignments))s in o&&(o[s]=a);return this._plugins.runResolve(o),o}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context),i=$(t,n,e.defaults);return this._plugins.runResolve(i),i},e.defaults)}decide(e){return this._errorBoundary.capture("decide",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let s=this._state.serverResponse,a={...e.defaults};for(let[h,T]of Object.entries(s.assignments))h in a&&(a[h]=T);let c={decisionId:s.decisionId,assignments:a,metadata:s.metadata};return this._cacheDecision(c),this._updateCumulativeAttribution(c),this._plugins.runDecision(c),c}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context);n=this._plugins.runBeforeDecision(n);let i=this._state.cachedEdgeResults??void 0,o=V(t,n,e.defaults,i);return this._cacheDecision(o),this._updateCumulativeAttribution(o),this._plugins.runDecision(o),o},{decisionId:S(),assignments:e.defaults,metadata:{timestamp:new Date().toISOString(),unitKeyValue:"",layers:[]}})}trackExposure(e){this._errorBoundary.capture("trackExposure",()=>{let t=e.metadata.unitKeyValue;if(t)for(let n of e.metadata.layers){if(!n.policyId||!n.allocationName||n.attributionOnly||!this._exposureDedup.checkAndMark(t,n.policyId,n.allocationName))continue;let o={type:"exposure",id:J(),decisionId:e.decisionId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:t,timestamp:new Date().toISOString(),assignments:e.assignments,layers:e.metadata.layers,context:e.metadata.filteredContext,sdkName:ce,sdkVersion:ue};this._plugins.runExposure(o)&&this._eventLogger.log(o)}},void 0)}track(e,t,n){this._errorBoundary.capture("track",()=>{let i=n?.unitKey??this._stableId.getId(),o=typeof t?.value=="number"?t.value:void 0,s=this._buildAttribution(i,n?.decisionId),a=n?.decisionId,c={type:"track",id:Y(),orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:i,timestamp:new Date().toISOString(),event:e,value:o,properties:t,decisionId:a,attribution:s,sdkName:ce,sdkVersion:ue};this._plugins.runTrack(c)&&this._eventLogger.log(c)},void 0)}async flushEvents(){await this._errorBoundary.swallow("flushEvents",async()=>{await this._eventLogger.flush()})}use(e){return this._plugins.register(e),this}getPlugin(e){return this._plugins.get(e)}getStableId(){return this._stableId.getId()}setStableId(e){this._stableId.setId(e)}_getEffectiveBundle(){return this._state.bundle??this._options.localConfig??null}_enrichContext(e){let n=this._getEffectiveBundle()?.hashing?.unitKey??"userId";return e[n]?e:{...e,[n]:this._stableId.getId()}}async _fetchConfig(){let e=`${this._options.baseUrl}/v1/config/${this._options.projectId}?env=${this._options.env}`,t={"Content-Type":"application/json",Authorization:`Bearer ${this._options.apiKey}`};this._state.etag&&(t["If-None-Match"]=this._state.etag);try{let n=await fetch(e,{method:"GET",headers:t});if(n.status===304){this._state.lastFetchTime=Date.now();return}if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);let i=await n.json(),o=n.headers.get("ETag");if(this._state.bundle=i,this._state.etag=o,this._state.lastFetchTime=Date.now(),this._findEdgePolicies(i).length>0){let s=await this._prefetchEdgeResults(i,this._enrichContext({}));this._state.cachedEdgeResults=s}else this._state.cachedEdgeResults=null;this._plugins.runConfigUpdate(i)}catch(n){this._logOfflineWarning(n)}}_startBackgroundRefresh(){let e=this._options.evaluationMode==="server"?this._state.serverResponse?.suggestedRefreshMs??this._options.refreshIntervalMs:this._options.refreshIntervalMs;e<=0||(this._state.refreshTimer=setInterval(()=>{this._options.evaluationMode==="server"?this._fetchServerResolve().catch(()=>{}):this._fetchConfig().catch(()=>{})},e))}async _fetchServerResolve(){if(this._decisionClient)try{let e=this._enrichContext({}),t=await this._decisionClient.resolve({context:e});t&&(this._state.serverResponse=t,this._state.lastFetchTime=Date.now())}catch(e){this._logOfflineWarning(e)}}_findEdgePolicies(e){let t=[];for(let n of e.layers)for(let i of n.policies)i.state==="running"&&i.entityConfig?.resolutionMode==="edge"&&t.push(i);return t}async _prefetchEdgeResults(e,t){if(!this._decisionClient)return{};let n=this._findEdgePolicies(e);if(n.length===0)return{};let i=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 Z(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 h=s[c];h&&a.set(o[c].policyId,{allocationIndex:h.allocationIndex,entityId:o[c].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>at&&(console.warn(`[Traffical] Failed to fetch config: ${e instanceof Error?e.message:String(e)}. Using ${this._state.bundle?"cached":"local"} config.`),this._state.lastOfflineWarning=t)}_cacheDecision(e){if(this._decisionCache.size>=lt){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 de(r){let e=new b(r);return await e.initialize(),e}function fe(r){return new b(r)}function ge(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(l,d){try{return new RegExp(l).test(d)}catch{return d===l}}function a(l,d,p){if(d==="innerHTML")l.innerHTML=p;else if(d==="textContent")l.textContent=p;else if(d==="src"&&"src"in l)l.src=p;else if(d==="href"&&"href"in l)l.href=p;else if(d.startsWith("style.")){let g=d.slice(6);l.style[g]=p}else l.setAttribute(d,p)}function c(l,d){let p=String(d);try{let g=document.querySelectorAll(l.selector);for(let u of g)a(u,l.property,p)}catch(g){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${l.parameterKey}:`,g)}}function h(l,d=!1){n=l;let p=typeof window<"u"?window.location.pathname:"";for(let g of t){if(!d&&!s(g.urlPattern,p))continue;let u=l[g.parameterKey];u!==void 0&&c(g,u)}}function T(){o&&clearTimeout(o),o=setTimeout(()=>{h(n)},e.debounceMs)}function f(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{T()}),i.observe(document.body,{childList:!0,subtree:!0}))}function v(){i&&(i.disconnect(),i=null),o&&(clearTimeout(o),o=null)}return{name:"dom-binding",onInitialize(){e.observeMutations&&f()},onConfigUpdate(l){t=l.domBindings??[]},onResolve(l){h(l)},onDecision(l){h(l.assignments)},onDestroy(){v(),t=[],n={}},applyBindings(l){h(l||n)},getBindings(){return t}}}var m=null;async function ct(r){return m?(console.warn("[Traffical] Client already initialized. Returning existing instance."),m):(m=await de(r),m)}function ut(r){return m?(console.warn("[Traffical] Client already initialized. Returning existing instance."),m):(m=fe(r),m.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),m)}function dt(){return m}function ft(){m&&(m.destroy(),m=null)}return Ee(gt);})();
1
+ /* @traffical/js-client v0.5.0 */
2
+ "use strict";var Traffical=(()=>{var R=Object.defineProperty;var me=Object.getOwnPropertyDescriptor;var _e=Object.getOwnPropertyNames;var ve=Object.prototype.hasOwnProperty;var be=(r,e,t)=>e in r?R(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var Ie=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Te=(r,e)=>{for(var t in e)R(r,t,{get:e[t],enumerable:!0})},Ee=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of _e(e))!ve.call(r,i)&&i!==t&&R(r,i,{get:()=>e[i],enumerable:!(n=me(e,i))||n.enumerable});return r};var xe=r=>Ee(R({},"__esModule",{value:!0}),r);var I=(r,e,t)=>(be(r,typeof e!="symbol"?e+"":e,t),t);var oe=Ie(()=>{});var It={};Te(It,{TrafficalClient:()=>x,createDOMBindingPlugin:()=>ye,createRedirectAttributionPlugin:()=>ie,createRedirectPlugin:()=>ne,destroy:()=>bt,init:()=>mt,initSync:()=>_t,instance:()=>vt});function E(r){let e=2166136261;for(let t=0;t<r.length;t++)e^=r.charCodeAt(t),e=Math.imul(e,16777619);return e>>>0}function O(r,e,t){let n=`${r}:${e}`;return E(n)%t}function q(r,e){return r>=e[0]&&r<=e[1]}function B(r,e){for(let t of e)if(q(r,t.bucketRange))return t;return null}function X(r,e){let{field:t,op:n,value:i,values:o}=r,s=Pe(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 N(r,e){return r.length===0?!0:r.every(t=>X(t,e))}function Pe(r,e){let t=e.split("."),n=r;for(let i of t){if(n==null)return;if(typeof n=="object")n=n[i];else return}return n}var we=r=>crypto.getRandomValues(new Uint8Array(r)),Se=(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}}},re=(r,e=21)=>Se(r,e|0,we);function L(r){let e=new Error(r);return e.source="ulid",e}var G="0123456789ABCDEFGHJKMNPQRSTVWXYZ",C=G.length,se=Math.pow(2,48)-1,Ae=10,De=16;function Me(r){let e=Math.floor(r()*C);return e===C&&(e=C-1),G.charAt(e)}function Re(r,e){if(isNaN(r))throw new Error(r+" must be a number");if(r>se)throw L("cannot encode time greater than "+se);if(r<0)throw L("time must be positive");if(Number.isInteger(Number(r))===!1)throw L("time must be an integer");let t,n="";for(;e>0;e--)t=r%C,n=G.charAt(t)+n,r=(r-t)/C;return n}function Oe(r,e){let t="";for(;r>0;r--)t=Me(e)+t;return t}function Be(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=oe();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 L("secure crypto unusable, insecure Math.random not allowed")}function Ne(r){return r||(r=Be()),function(t){return isNaN(t)&&(t=Date.now()),Re(t,Ae)+Oe(De,r)}}var ae=Ne();var Le="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Ke=8,Nt=re(Le,Ke);function K(r){return`${r}_${ae()}`}function P(){return K("dec")}function J(){return K("exp")}function Y(){return K("trk")}function Ve(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 $e(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 Fe(r,e){if(r.length===0||r.length===1)return 0;let n=E(e)%1e4/1e4,i=0;for(let o=0;o<r.length;o++)if(i+=r[o],n<i)return o;return r.length-1}function le(r){if(r<=0)return[];let e=1/r;return Array(r).fill(e)}function Ue(r,e,t,n){let i=r.entityState?.[e];if(!i)return le(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:le(n)}function je(r,e,t,n){let i=e.entityConfig;if(!i)return null;let o=$e(i.entityKeys,t);if(!o)return null;let s,a;if(i.dynamicAllocations){let f=i.dynamicAllocations.countKey,_=t[f];if(typeof _!="number"||_<=0)return null;a=Math.floor(_),s=Array.from({length:a},(l,d)=>({id:`${e.id}_dynamic_${d}`,name:String(d),bucketRange:[0,0],overrides:{}}))}else s=e.allocations,a=s.length;if(a===0)return null;let c=Ue(r,e.id,o,a),p=`${o}:${n}:${e.id}`,b=Fe(c,p);return{allocation:s[b],entityId:o}}function w(r,e){let t=e[r.hashing.unitKey];return t==null?null:String(t)}function ce(r,e,t,n){let i={...t},o=[],s=[];if(!r)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let a=w(r,e);if(!a)return{assignments:i,unitKeyValue:"",layers:o,matchedPolicies:s};let c=new Set(Object.keys(t)),p=r.parameters.filter(f=>c.has(f.key));for(let f of p)f.key in i&&(i[f.key]=f.default);let b=new Map;for(let f of p){let _=b.get(f.layerId)||[];_.push(f),b.set(f.layerId,_)}for(let f of r.layers){let _=b.get(f.id),l=_&&_.length>0,d=O(a,f.id,r.hashing.bucketCount),h,g;for(let u of f.policies)if(u.state==="running"){if(u.eligibleBucketRange){let{start:y,end:v}=u.eligibleBucketRange;if(d<y||d>v)continue}if(N(u.conditions,e))if(u.entityConfig&&u.entityConfig.resolutionMode==="bundle"){let y=je(r,u,e,a);if(y){if(h=u,g=y.allocation,s.push(u),l&&!u.entityConfig.dynamicAllocations)for(let[v,k]of Object.entries(y.allocation.overrides))v in i&&(i[v]=k);break}}else if(u.entityConfig&&u.entityConfig.resolutionMode==="edge"){let y=n?.edgeResults?.get(u.id);if(y){if(h=u,s.push(u),u.entityConfig.dynamicAllocations)g={id:`${u.id}_dynamic_${y.allocationIndex}`,name:String(y.allocationIndex),bucketRange:[0,0],overrides:{}};else if(u.allocations[y.allocationIndex]&&(g=u.allocations[y.allocationIndex],l&&g))for(let[v,k]of Object.entries(g.overrides))v in i&&(i[v]=k);break}continue}else{let y=B(d,u.allocations);if(y){if(h=u,g=y,s.push(u),l)for(let[v,k]of Object.entries(y.overrides))v in i&&(i[v]=k);break}}}o.push({layerId:f.id,bucket:d,policyId:h?.id,allocationId:g?.id,allocationName:g?.name,...l?{}:{attributionOnly:!0}})}return{assignments:i,unitKeyValue:a,layers:o,matchedPolicies:s}}function V(r,e,t,n){return ce(r,e,t,n).assignments}function $(r,e,t,n){let{assignments:i,unitKeyValue:o,layers:s,matchedPolicies:a}=ce(r,e,t,n),c=Ve(e,a);return{decisionId:P(),assignments:i,metadata:{timestamp:new Date().toISOString(),unitKeyValue:o,layers:s,filteredContext:c}}}var T=class r{constructor(e={}){I(this,"_seen",new Map);I(this,"_ttlMs");I(this,"_maxEntries");I(this,"_lastCleanup",Date.now());this._ttlMs=e.ttlMs??36e5,this._maxEntries=e.maxEntries??1e4}static hashAssignments(e){let t=Object.keys(e).sort(),n=[];for(let i of t){let o=e[i],s=typeof o=="object"?JSON.stringify(o):String(o);n.push(`${i}=${s}`)}return n.join("|")}static createKey(e,t){return`${e}:${t}`}checkAndMark(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o!==void 0&&i-o<this._ttlMs?!1:(this._seen.set(n,i),this._maybeCleanup(i),!0)}wouldBeNew(e,t){let n=r.createKey(e,t),i=Date.now(),o=this._seen.get(n);return o===void 0?!0:i-o>=this._ttlMs}clear(){this._seen.clear()}get size(){return this._seen.size}_maybeCleanup(e){(e-this._lastCleanup>this._ttlMs*.2||this._seen.size>this._maxEntries)&&(this._lastCleanup=e,this._cleanup(e))}_cleanup(e){let t=[];for(let[n,i]of this._seen.entries())e-i>=this._ttlMs&&t.push(n);for(let n of t)this._seen.delete(n);if(this._seen.size>this._maxEntries){let i=Array.from(this._seen.entries()).sort((o,s)=>o[1]-s[1]).slice(0,this._seen.size-this._maxEntries);for(let[o]of i)this._seen.delete(o)}}};var S=class{constructor(e){I(this,"config");I(this,"defaultTimeout");this.config=e,this.defaultTimeout=e.defaultTimeoutMs??5e3}async resolve(e){try{let t=new AbortController,n=setTimeout(()=>t.abort(),this.defaultTimeout),i=`${this.config.baseUrl}/v1/resolve`,o=await fetch(i,{method:"POST",headers:this._headers(),body:JSON.stringify({context:e.context,env:e.env??this.config.env,parameters:e.parameters}),signal:t.signal});return clearTimeout(n),o.ok?await o.json():(console.warn(`[Traffical] Resolve failed: ${o.status} ${o.statusText}`),null)}catch(t){return t instanceof Error&&t.name==="AbortError"?console.warn(`[Traffical] Resolve timed out after ${this.defaultTimeout}ms`):console.warn("[Traffical] Resolve error:",t),null}}async decideEntity(e,t){let n=t??Math.min(this.defaultTimeout,100);try{let i=new AbortController,o=setTimeout(()=>i.abort(),n),s=`${this.config.baseUrl}/v1/decide/${e.policyId}`,a=await fetch(s,{method:"POST",headers:this._headers(),body:JSON.stringify({entityId:e.entityId,unitKeyValue:e.unitKeyValue,allocationCount:e.allocationCount,context:e.context}),signal:i.signal});return clearTimeout(o),a.ok?await a.json():(console.warn(`[Traffical] Edge decide failed: ${a.status} ${a.statusText}`),null)}catch(i){return i instanceof Error&&i.name==="AbortError"?console.warn(`[Traffical] Edge decide timed out after ${n}ms`):console.warn("[Traffical] Edge decide error:",i),null}}async decideEntityBatch(e,t){if(e.length===0)return[];if(e.length===1)return[await this.decideEntity(e[0],t)];let n=t??Math.min(this.defaultTimeout,200);try{let i=new AbortController,o=setTimeout(()=>i.abort(),n),s=`${this.config.baseUrl}/v1/decide/batch`,a=await fetch(s,{method:"POST",headers:this._headers(),body:JSON.stringify({requests:e}),signal:i.signal});return clearTimeout(o),a.ok?(await a.json()).responses:(console.warn(`[Traffical] Edge batch decide failed: ${a.status} ${a.statusText}`),e.map(()=>null))}catch(i){return i instanceof Error&&i.name==="AbortError"?console.warn(`[Traffical] Edge batch decide timed out after ${n}ms`):console.warn("[Traffical] Edge batch decide error:",i),e.map(()=>null)}}_headers(){return{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`,"X-Org-Id":this.config.orgId,"X-Project-Id":this.config.projectId,"X-Env":this.config.env}}};function Z(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 F=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 U="failed_events";var j=class{constructor(e){this._queue=[];this._flushTimer=null;this._isFlushing=!1;this._endpoint=e.endpoint,this._apiKey=e.apiKey,this._storage=e.storage,this._batchSize=e.batchSize??10,this._flushIntervalMs=e.flushIntervalMs??3e4,this._onError=e.onError,this._lifecycleProvider=e.lifecycleProvider,this._setupListeners(),this._retryFailedEvents(),this._startFlushTimer()}log(e){this._queue.push(e),this._queue.length>=this._batchSize&&this.flush()}async flush(){if(this._isFlushing||this._queue.length===0)return;this._isFlushing=!0;let e=[...this._queue];this._queue=[];try{await this._sendEvents(e)}catch(t){this._persistFailedEvents(e),this._onError?.(t instanceof Error?t:new Error(String(t)))}finally{this._isFlushing=!1}}flushBeacon(){if(this._queue.length===0)return!0;if(typeof fetch>"u")return this.flush(),!1;let e=[...this._queue];return this._queue=[],fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e}),keepalive:!0}).catch(()=>{this._persistFailedEvents(e)}),!0}get queueSize(){return this._queue.length}destroy(){this._flushTimer&&(clearInterval(this._flushTimer),this._flushTimer=null),this._removeListeners()}async _sendEvents(e){let t=await fetch(this._endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this._apiKey}`},body:JSON.stringify({events:e})});if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`)}_persistFailedEvents(e){let n=[...this._storage.get(U)??[],...e].slice(-100);this._storage.set(U,n)}_retryFailedEvents(){let e=this._storage.get(U);!e||e.length===0||(this._storage.remove(U),this._queue.push(...e))}_startFlushTimer(){this._flushIntervalMs<=0||(this._flushTimer=setInterval(()=>{this.flush().catch(()=>{})},this._flushIntervalMs))}_setupListeners(){this._lifecycleProvider&&(this._visibilityCallback=e=>{e==="background"?this._lifecycleProvider?.isUnloading()?this.flushBeacon():this.flush().catch(()=>{}):this._retryFailedEvents()},this._lifecycleProvider.onVisibilityChange(this._visibilityCallback))}_removeListeners(){this._lifecycleProvider&&this._visibilityCallback&&(this._lifecycleProvider.removeVisibilityListener(this._visibilityCallback),this._visibilityCallback=void 0)}};var A="exposure_dedup";var z=class r{constructor(e){this._storage=e.storage,this._sessionTtlMs=e.sessionTtlMs??18e5,this._seen=new Set,this._sessionStart=Date.now(),this._restore()}static createKey(e,t,n){return`${e}:${t}:${n}`}shouldTrack(e){return this._isSessionExpired()&&this._resetSession(),this._seen.has(e)?!1:(this._seen.add(e),this._persist(),!0)}checkAndMark(e,t,n){let i=r.createKey(e,t,n);return this.shouldTrack(i)}clear(){this._seen.clear(),this._storage.remove(A)}get size(){return this._seen.size}_isSessionExpired(){return Date.now()-this._sessionStart>this._sessionTtlMs}_resetSession(){this._seen.clear(),this._sessionStart=Date.now(),this._storage.remove(A)}_persist(){let e={seen:Array.from(this._seen),sessionStart:this._sessionStart};this._storage.set(A,e,this._sessionTtlMs)}_restore(){let e=this._storage.get(A);if(!e)return;if(Date.now()-e.sessionStart>this._sessionTtlMs){this._storage.remove(A);return}this._seen=new Set(e.seen),this._sessionStart=e.sessionStart}};var D="stable_id",rt="traffical_sid";var W=class{constructor(e){this._cachedId=null;this._storage=e.storage,this._useCookieFallback=e.useCookieFallback??!0,this._cookieName=e.cookieName??rt}getId(){if(this._cachedId)return this._cachedId;let e=this._storage.get(D);return e?(this._cachedId=e,e):this._useCookieFallback&&(e=this._getCookie(),e)?(this._storage.set(D,e),this._cachedId=e,e):(e=this._generateId(),this._persist(e),this._cachedId=e,e)}setId(e){this._persist(e),this._cachedId=e}clear(){this._storage.remove(D),this._useCookieFallback&&this._deleteCookie(),this._cachedId=null}hasId(){return this._storage.get(D)!==null||this._getCookie()!==null}_persist(e){this._storage.set(D,e),this._useCookieFallback&&this._setCookie(e)}_generateId(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}_getCookie(){if(typeof document>"u")return null;try{let e=document.cookie.split(";");for(let t of e){let[n,i]=t.trim().split("=");if(n===this._cookieName&&i)return decodeURIComponent(i)}}catch{}return null}_setCookie(e){if(!(typeof document>"u"))try{document.cookie=`${this._cookieName}=${encodeURIComponent(e)}; max-age=31536000; path=/; SameSite=Lax`}catch{}}_deleteCookie(){if(!(typeof document>"u"))try{document.cookie=`${this._cookieName}=; max-age=0; path=/`}catch{}}};var M="traffical:",Q=class{constructor(){this._available=this._checkAvailability()}get(e){if(!this._available)return null;try{let t=localStorage.getItem(M+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(M+e,JSON.stringify(i))}catch{}}remove(e){if(this._available)try{localStorage.removeItem(M+e)}catch{}}clear(){if(this._available)try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n?.startsWith(M)&&e.push(n)}e.forEach(t=>localStorage.removeItem(t))}catch{}}_checkAvailability(){try{let e=M+"__test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}},ee=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 ue(){let r=new Q;return r.get("__check__")!==null||ot()?r:new ee}function ot(){try{let r="__traffical_storage_test__";return localStorage.setItem(r,"test"),localStorage.removeItem(r),!0}catch{return!1}}var st="js-client",at="0.1.0";function te(r,e){let t=new T({ttlMs:r.deduplicationTtlMs});return{name:"decision-tracking",onDecision(n){if(r.disabled)return;let i=n.metadata.unitKeyValue;if(!i)return;let o=T.hashAssignments(n.assignments);if(!t.checkAndMark(i,o))return;let s={type:"decision",id:n.decisionId,orgId:e.orgId,projectId:e.projectId,env:e.env,unitKey:i,timestamp:n.metadata.timestamp,assignments:n.assignments,layers:n.metadata.layers,context:n.metadata.filteredContext,sdkName:st,sdkVersion:at};e.log(s)},onDestroy(){t.clear()}}}var lt="traffical_rdr";function ct(r,e,t){if(!(typeof document>"u"))try{document.cookie=`${r}=${encodeURIComponent(e)}; max-age=${t}; path=/; SameSite=Lax`}catch{}}function ne(r={}){let e=r.parameterKey??"redirect.url",t=r.compareMode??"pathname",n=r.cookieName??lt;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&&ct(n,JSON.stringify({l:a.layerId,p:a.policyId,a:a.allocationName,ts:Date.now()}),86400),window.location.replace(o)}}}var ut="traffical_rdr";function dt(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 ft(r,e){let t=dt(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 ie(r={}){let e=r.cookieName??ut,t=r.expiryMs??864e5;function n(i){let o=ft(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 H=class{constructor(){this._plugins=[]}register(e){let t="plugin"in e?e.plugin:e,n="priority"in e?e.priority??0:0;if(this._plugins.some(i=>i.plugin.name===t.name)){console.warn(`[Traffical] Plugin "${t.name}" already registered, skipping.`);return}this._plugins.push({plugin:t,priority:n}),this._plugins.sort((i,o)=>o.priority-i.priority)}unregister(e){let t=this._plugins.findIndex(n=>n.plugin.name===e);return t===-1?!1:(this._plugins.splice(t,1),!0)}get(e){return this._plugins.find(t=>t.plugin.name===e)?.plugin}getAll(){return this._plugins.map(e=>e.plugin)}async runInitialize(e){for(let{plugin:t}of this._plugins)if(t.onInitialize)try{await t.onInitialize(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onInitialize error:`,n)}}runConfigUpdate(e){for(let{plugin:t}of this._plugins)if(t.onConfigUpdate)try{t.onConfigUpdate(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onConfigUpdate error:`,n)}}runBeforeDecision(e){let t=e;for(let{plugin:n}of this._plugins)if(n.onBeforeDecision)try{let i=n.onBeforeDecision(t);i&&(t=i)}catch(i){console.warn(`[Traffical] Plugin "${n.name}" onBeforeDecision error:`,i)}return t}runDecision(e){for(let{plugin:t}of this._plugins)if(t.onDecision)try{t.onDecision(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onDecision error:`,n)}}runResolve(e){for(let{plugin:t}of this._plugins)if(t.onResolve)try{t.onResolve(e)}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onResolve error:`,n)}}runExposure(e){for(let{plugin:t}of this._plugins)if(t.onExposure)try{if(t.onExposure(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onExposure error:`,n)}return!0}runTrack(e){for(let{plugin:t}of this._plugins)if(t.onTrack)try{if(t.onTrack(e)===!1)return!1}catch(n){console.warn(`[Traffical] Plugin "${t.name}" onTrack error:`,n)}return!0}runDestroy(){for(let{plugin:e}of this._plugins)if(e.onDestroy)try{e.onDestroy()}catch(t){console.warn(`[Traffical] Plugin "${e.name}" onDestroy error:`,t)}}clear(){this._plugins=[]}};function de(){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 fe="js-client",ge="0.1.0",gt="https://sdk.traffical.io",pt=6e4,ht=3e5,yt=100,x=class{constructor(e){this._state={bundle:null,etag:null,lastFetchTime:0,lastOfflineWarning:0,refreshTimer:null,isInitialized:!1,serverResponse:null,cachedEdgeResults:null};this._decisionCache=new Map;this._cumulativeAttribution=new Map;let t=e.evaluationMode??"bundle";this._options={orgId:e.orgId,projectId:e.projectId,env:e.env,apiKey:e.apiKey,baseUrl:e.baseUrl??gt,localConfig:e.localConfig,refreshIntervalMs:e.refreshIntervalMs??pt,attributionMode:e.attributionMode??"cumulative",evaluationMode:t};let n={baseUrl:this._options.baseUrl,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,apiKey:this._options.apiKey};if(this._decisionClient=new S(n),this._errorBoundary=new F(e.errorBoundary),this._storage=e.storage??ue(),this._lifecycleProvider=e.lifecycleProvider??de(),this._eventLogger=new j({endpoint:`${this._options.baseUrl}/v1/events/batch`,apiKey:e.apiKey,storage:this._storage,lifecycleProvider:this._lifecycleProvider,batchSize:e.eventBatchSize,flushIntervalMs:e.eventFlushIntervalMs,onError:i=>{console.warn("[Traffical] Event logging error:",i.message)}}),this._exposureDedup=new z({storage:this._storage,sessionTtlMs:e.exposureSessionTtlMs}),this._stableId=new W({storage:this._storage}),this._plugins=new H,e.trackDecisions!==!1&&this._plugins.register({plugin:te({deduplicationTtlMs:e.decisionDeduplicationTtlMs},{orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,log:i=>this._eventLogger.log(i)}),priority:100}),e.plugins)for(let i of e.plugins)this._plugins.register(i);this._options.localConfig&&(this._state.bundle=this._options.localConfig,this._plugins.runConfigUpdate(this._options.localConfig))}async initialize(){await this._errorBoundary.captureAsync("initialize",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig(),this._startBackgroundRefresh(),this._state.isInitialized=!0,await this._plugins.runInitialize(this)},void 0)}get isInitialized(){return this._state.isInitialized}destroy(){this._state.refreshTimer&&(clearInterval(this._state.refreshTimer),this._state.refreshTimer=null),this._lifecycleProvider.isUnloading()?this._eventLogger.flushBeacon():this._eventLogger.flush().catch(()=>{}),this._eventLogger.destroy(),this._plugins.runDestroy()}async refreshConfig(){await this._errorBoundary.swallow("refreshConfig",async()=>{this._options.evaluationMode==="server"?await this._fetchServerResolve():await this._fetchConfig()})}getConfigVersion(){return this._state.serverResponse?.stateVersion??this._state.bundle?.version??null}getParams(e){return this._errorBoundary.capture("getParams",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let o={...e.defaults};for(let[s,a]of Object.entries(this._state.serverResponse.assignments))s in o&&(o[s]=a);return this._plugins.runResolve(o),o}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context),i=V(t,n,e.defaults);return this._plugins.runResolve(i),i},e.defaults)}decide(e){return this._errorBoundary.capture("decide",()=>{if(this._options.evaluationMode==="server"&&this._state.serverResponse){let s=this._state.serverResponse,a={...e.defaults};for(let[p,b]of Object.entries(s.assignments))p in a&&(a[p]=b);let c={decisionId:s.decisionId,assignments:a,metadata:s.metadata};return this._cacheDecision(c),this._updateCumulativeAttribution(c),this._plugins.runDecision(c),c}let t=this._getEffectiveBundle(),n=this._enrichContext(e.context);n=this._plugins.runBeforeDecision(n);let i=this._state.cachedEdgeResults??void 0,o=$(t,n,e.defaults,i);return this._cacheDecision(o),this._updateCumulativeAttribution(o),this._plugins.runDecision(o),o},{decisionId:P(),assignments:e.defaults,metadata:{timestamp:new Date().toISOString(),unitKeyValue:"",layers:[]}})}trackExposure(e){this._errorBoundary.capture("trackExposure",()=>{let t=e.metadata.unitKeyValue;if(t)for(let n of e.metadata.layers){if(!n.policyId||!n.allocationName||n.attributionOnly||!this._exposureDedup.checkAndMark(t,n.policyId,n.allocationName))continue;let o={type:"exposure",id:J(),decisionId:e.decisionId,orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:t,timestamp:new Date().toISOString(),assignments:e.assignments,layers:e.metadata.layers,context:e.metadata.filteredContext,sdkName:fe,sdkVersion:ge};this._plugins.runExposure(o)&&this._eventLogger.log(o)}},void 0)}track(e,t,n){this._errorBoundary.capture("track",()=>{let i=n?.unitKey??this._stableId.getId(),o=typeof t?.value=="number"?t.value:void 0,s=this._buildAttribution(i,n?.decisionId),a=n?.decisionId,c={type:"track",id:Y(),orgId:this._options.orgId,projectId:this._options.projectId,env:this._options.env,unitKey:i,timestamp:new Date().toISOString(),event:e,value:o,properties:t,decisionId:a,attribution:s,sdkName:fe,sdkVersion:ge};this._plugins.runTrack(c)&&this._eventLogger.log(c)},void 0)}async flushEvents(){await this._errorBoundary.swallow("flushEvents",async()=>{await this._eventLogger.flush()})}use(e){return this._plugins.register(e),this}getPlugin(e){return this._plugins.get(e)}getStableId(){return this._stableId.getId()}setStableId(e){this._stableId.setId(e)}_getEffectiveBundle(){return this._state.bundle??this._options.localConfig??null}_enrichContext(e){let n=this._getEffectiveBundle()?.hashing?.unitKey??"userId";return e[n]?e:{...e,[n]:this._stableId.getId()}}async _fetchConfig(){let e=`${this._options.baseUrl}/v1/config/${this._options.projectId}?env=${this._options.env}`,t={"Content-Type":"application/json",Authorization:`Bearer ${this._options.apiKey}`};this._state.etag&&(t["If-None-Match"]=this._state.etag);try{let n=await fetch(e,{method:"GET",headers:t});if(n.status===304){this._state.lastFetchTime=Date.now();return}if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);let i=await n.json(),o=n.headers.get("ETag");if(this._state.bundle=i,this._state.etag=o,this._state.lastFetchTime=Date.now(),this._findEdgePolicies(i).length>0){let s=await this._prefetchEdgeResults(i,this._enrichContext({}));this._state.cachedEdgeResults=s}else this._state.cachedEdgeResults=null;this._plugins.runConfigUpdate(i)}catch(n){this._logOfflineWarning(n)}}_startBackgroundRefresh(){let e=this._options.evaluationMode==="server"?this._state.serverResponse?.suggestedRefreshMs??this._options.refreshIntervalMs:this._options.refreshIntervalMs;e<=0||(this._state.refreshTimer=setInterval(()=>{this._options.evaluationMode==="server"?this._fetchServerResolve().catch(()=>{}):this._fetchConfig().catch(()=>{})},e))}async _fetchServerResolve(){if(this._decisionClient)try{let e=this._enrichContext({}),t=await this._decisionClient.resolve({context:e});t&&(this._state.serverResponse=t,this._state.lastFetchTime=Date.now())}catch(e){this._logOfflineWarning(e)}}_findEdgePolicies(e){let t=[];for(let n of e.layers)for(let i of n.policies)i.state==="running"&&i.entityConfig?.resolutionMode==="edge"&&t.push(i);return t}async _prefetchEdgeResults(e,t){if(!this._decisionClient)return{};let n=this._findEdgePolicies(e);if(n.length===0)return{};let i=w(e,t);if(!i)return{};let o=n.map(s=>{if(!s.entityConfig)return null;let a=s.entityConfig.dynamicAllocations?typeof t[s.entityConfig.dynamicAllocations.countKey]=="number"?Math.floor(t[s.entityConfig.dynamicAllocations.countKey]):0:s.allocations.length;return Z(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 p=s[c];p&&a.set(o[c].policyId,{allocationIndex:p.allocationIndex,entityId:o[c].entityId})}return a.size>0?{edgeResults:a}:{}}catch{return{}}}_logOfflineWarning(e){let t=Date.now();t-this._state.lastOfflineWarning>ht&&(console.warn(`[Traffical] Failed to fetch config: ${e instanceof Error?e.message:String(e)}. Using ${this._state.bundle?"cached":"local"} config.`),this._state.lastOfflineWarning=t)}_cacheDecision(e){if(this._decisionCache.size>=yt){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 pe(r){let e=new x(r);return await e.initialize(),e}function he(r){return new x(r)}function ye(r={}){let e={observeMutations:r.observeMutations??!0,debounceMs:r.debounceMs??100},t=[],n={},i=null,o=null;function s(l,d){try{return new RegExp(l).test(d)}catch{return d===l}}function a(l,d,h){if(d==="innerHTML")l.innerHTML=h;else if(d==="textContent")l.textContent=h;else if(d==="src"&&"src"in l)l.src=h;else if(d==="href"&&"href"in l)l.href=h;else if(d.startsWith("style.")){let g=d.slice(6);l.style[g]=h}else l.setAttribute(d,h)}function c(l,d){let h=String(d);try{let g=document.querySelectorAll(l.selector);for(let u of g)a(u,l.property,h)}catch(g){console.warn(`[Traffical DOM Binding] Failed to apply binding for ${l.parameterKey}:`,g)}}function p(l,d=!1){n=l;let h=typeof window<"u"?window.location.pathname:"";for(let g of t){if(!d&&!s(g.urlPattern,h))continue;let u=l[g.parameterKey];u!==void 0&&c(g,u)}}function b(){o&&clearTimeout(o),o=setTimeout(()=>{p(n)},e.debounceMs)}function f(){i||typeof MutationObserver>"u"||typeof document>"u"||(i=new MutationObserver(()=>{b()}),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&&f()},onConfigUpdate(l){t=l.domBindings??[]},onResolve(l){p(l)},onDecision(l){p(l.assignments)},onDestroy(){_(),t=[],n={}},applyBindings(l){p(l||n)},getBindings(){return t}}}var m=null;async function mt(r){return m?(console.warn("[Traffical] Client already initialized. Returning existing instance."),m):(m=await pe(r),m)}function _t(r){return m?(console.warn("[Traffical] Client already initialized. Returning existing instance."),m):(m=he(r),m.initialize().catch(e=>{console.warn("[Traffical] Initialization error:",e)}),m)}function vt(){return m}function bt(){m&&(m.destroy(),m=null)}return xe(It);})();
3
3
  //# sourceMappingURL=traffical.min.js.map