@xenia-martech/sdk-js 1.0.1-dev.1 → 1.1.0-dev.1

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.
Files changed (54) hide show
  1. package/README.md +53 -4
  2. package/dist/{actions-CcBYV--3.d.cts → actions-CKeiofxJ.d.cts} +19 -1
  3. package/dist/{actions-CcBYV--3.d.ts → actions-CKeiofxJ.d.ts} +19 -1
  4. package/dist/{cookie-names-B3b0XNc2.d.cts → api-URhxxi4x.d.cts} +19 -42
  5. package/dist/{cookie-names-B3b0XNc2.d.ts → api-URhxxi4x.d.ts} +19 -42
  6. package/dist/chunk-5D7SJIO4.cjs +109 -0
  7. package/dist/chunk-5D7SJIO4.cjs.map +1 -0
  8. package/dist/chunk-BHNOKSJH.js +214 -0
  9. package/dist/chunk-BHNOKSJH.js.map +1 -0
  10. package/dist/{chunk-XXNDHYAS.js → chunk-FYSEKFIY.js} +45 -103
  11. package/dist/chunk-FYSEKFIY.js.map +1 -0
  12. package/dist/{chunk-WYM4CQVG.cjs → chunk-JEKVN7HK.cjs} +46 -106
  13. package/dist/chunk-JEKVN7HK.cjs.map +1 -0
  14. package/dist/chunk-LBRZMWE2.cjs +220 -0
  15. package/dist/chunk-LBRZMWE2.cjs.map +1 -0
  16. package/dist/chunk-TLTG3BTC.js +104 -0
  17. package/dist/chunk-TLTG3BTC.js.map +1 -0
  18. package/dist/client/index.cjs +60 -6
  19. package/dist/client/index.cjs.map +1 -1
  20. package/dist/client/index.d.cts +25 -3
  21. package/dist/client/index.d.ts +25 -3
  22. package/dist/client/index.js +59 -7
  23. package/dist/client/index.js.map +1 -1
  24. package/dist/client/react/index.cjs +58 -6
  25. package/dist/client/react/index.cjs.map +1 -1
  26. package/dist/client/react/index.d.cts +2 -2
  27. package/dist/client/react/index.d.ts +2 -2
  28. package/dist/client/react/index.js +58 -6
  29. package/dist/client/react/index.js.map +1 -1
  30. package/dist/cookie-names-8FxbGKGS.d.ts +127 -0
  31. package/dist/cookie-names-QYMiEMAq.d.cts +127 -0
  32. package/dist/index.cjs +41 -32
  33. package/dist/index.d.cts +4 -71
  34. package/dist/index.d.ts +4 -71
  35. package/dist/index.js +2 -1
  36. package/dist/next/index.cjs +59 -0
  37. package/dist/next/index.cjs.map +1 -0
  38. package/dist/next/index.d.cts +45 -0
  39. package/dist/next/index.d.ts +45 -0
  40. package/dist/next/index.js +54 -0
  41. package/dist/next/index.js.map +1 -0
  42. package/dist/server/index.cjs +38 -214
  43. package/dist/server/index.cjs.map +1 -1
  44. package/dist/server/index.d.cts +5 -104
  45. package/dist/server/index.d.ts +5 -104
  46. package/dist/server/index.js +5 -204
  47. package/dist/server/index.js.map +1 -1
  48. package/dist/xenia-sdk.iife.js +3 -3
  49. package/dist/xenia-sdk.iife.js.map +1 -1
  50. package/dist/xenia-server-BG4Vkaua.d.cts +110 -0
  51. package/dist/xenia-server-CpFUOxbB.d.ts +110 -0
  52. package/package.json +26 -7
  53. package/dist/chunk-WYM4CQVG.cjs.map +0 -1
  54. package/dist/chunk-XXNDHYAS.js.map +0 -1
@@ -0,0 +1,104 @@
1
+ // src/core/content-splice.ts
2
+ function isPlainObject(v) {
3
+ return v !== null && typeof v === "object" && !Array.isArray(v);
4
+ }
5
+ function cloneJson(value) {
6
+ return value === null || typeof value !== "object" ? value : JSON.parse(JSON.stringify(value));
7
+ }
8
+ function setAtPath(node, path, value, mode) {
9
+ if (path.length === 0) {
10
+ if (mode === "merge" && isPlainObject(node) && isPlainObject(value)) {
11
+ return { ...node, ...value };
12
+ }
13
+ return value;
14
+ }
15
+ const [key, ...rest] = path;
16
+ if (Array.isArray(node)) {
17
+ const index = Number(key);
18
+ if (!Number.isInteger(index) || index < 0 || index >= node.length) return node;
19
+ const next = node.slice();
20
+ next[index] = setAtPath(next[index], rest, value, mode);
21
+ return next;
22
+ }
23
+ if (isPlainObject(node)) {
24
+ if (!(key in node)) return node;
25
+ return { ...node, [key]: setAtPath(node[key], rest, value, mode) };
26
+ }
27
+ return node;
28
+ }
29
+ function spliceSlots(slots, swaps) {
30
+ const result = {};
31
+ for (const [key, value] of Object.entries(slots)) {
32
+ result[key] = cloneJson(value);
33
+ }
34
+ if (!swaps) return result;
35
+ for (const swap of swaps) {
36
+ const [slotKey, ...pathParts] = swap.identifier.split(".");
37
+ if (!(slotKey in result)) continue;
38
+ result[slotKey] = setAtPath(result[slotKey], pathParts, swap.replacement, swap.mode ?? "replace");
39
+ }
40
+ return result;
41
+ }
42
+ function extractContentSwaps(body) {
43
+ if (!isPlainObject(body)) return void 0;
44
+ const swaps = body.xeniaContentSwaps;
45
+ return Array.isArray(swaps) ? swaps : void 0;
46
+ }
47
+
48
+ // src/core/response-store.ts
49
+ var MemoryResponseStore = class {
50
+ map = /* @__PURE__ */ new Map();
51
+ set(key, value) {
52
+ this.map.set(key, value);
53
+ }
54
+ get(key) {
55
+ return this.map.get(key);
56
+ }
57
+ keys() {
58
+ return [...this.map.keys()];
59
+ }
60
+ clear() {
61
+ this.map.clear();
62
+ }
63
+ };
64
+ var LocalStorageResponseStore = class {
65
+ nsKey;
66
+ constructor(prefix = "xenia") {
67
+ this.nsKey = `${prefix}_responses`;
68
+ }
69
+ read() {
70
+ try {
71
+ const raw = localStorage.getItem(this.nsKey);
72
+ return raw ? JSON.parse(raw) : {};
73
+ } catch {
74
+ return {};
75
+ }
76
+ }
77
+ write(data) {
78
+ try {
79
+ localStorage.setItem(this.nsKey, JSON.stringify(data));
80
+ } catch {
81
+ }
82
+ }
83
+ set(key, value) {
84
+ const data = this.read();
85
+ data[key] = value;
86
+ this.write(data);
87
+ }
88
+ get(key) {
89
+ return this.read()[key];
90
+ }
91
+ keys() {
92
+ return Object.keys(this.read());
93
+ }
94
+ clear() {
95
+ try {
96
+ localStorage.removeItem(this.nsKey);
97
+ } catch {
98
+ }
99
+ }
100
+ };
101
+
102
+ export { LocalStorageResponseStore, MemoryResponseStore, extractContentSwaps, spliceSlots };
103
+ //# sourceMappingURL=chunk-TLTG3BTC.js.map
104
+ //# sourceMappingURL=chunk-TLTG3BTC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/content-splice.ts","../src/core/response-store.ts"],"names":[],"mappings":";AAoBA,SAAS,cAAc,CAAA,EAAiD;AACtE,EAAA,OAAO,CAAA,KAAM,QAAQ,OAAO,CAAA,KAAM,YAAY,CAAC,KAAA,CAAM,QAAQ,CAAC,CAAA;AAChE;AAEA,SAAS,UAA+B,KAAA,EAAa;AACnD,EAAA,OAAO,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAChG;AAEA,SAAS,SAAA,CAAU,IAAA,EAAiB,IAAA,EAAgB,KAAA,EAAkB,IAAA,EAAsC;AAC1G,EAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,IAAA,IAAI,SAAS,OAAA,IAAW,aAAA,CAAc,IAAI,CAAA,IAAK,aAAA,CAAc,KAAK,CAAA,EAAG;AACnE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,GAAG,KAAA,EAAM;AAAA,IAC7B;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,CAAC,GAAA,EAAK,GAAG,IAAI,CAAA,GAAI,IAAA;AACvB,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACvB,IAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AACxB,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA,IAAK,QAAQ,CAAA,IAAK,KAAA,IAAS,IAAA,CAAK,MAAA,EAAQ,OAAO,IAAA;AAC1E,IAAA,MAAM,IAAA,GAAO,KAAK,KAAA,EAAM;AACxB,IAAA,IAAA,CAAK,KAAK,IAAI,SAAA,CAAU,IAAA,CAAK,KAAK,CAAA,EAAG,IAAA,EAAM,OAAO,IAAI,CAAA;AACtD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,aAAA,CAAc,IAAI,CAAA,EAAG;AACvB,IAAA,IAAI,EAAE,GAAA,IAAO,IAAA,CAAA,EAAO,OAAO,IAAA;AAC3B,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,CAAC,GAAG,GAAG,SAAA,CAAU,IAAA,CAAK,GAAG,CAAA,EAAG,IAAA,EAAM,KAAA,EAAO,IAAI,CAAA,EAAE;AAAA,EACnE;AACA,EAAA,OAAO,IAAA;AACT;AASO,SAAS,WAAA,CACd,OACA,KAAA,EAC2B;AAC3B,EAAA,MAAM,SAAoC,EAAC;AAC3C,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAChD,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,SAAA,CAAU,KAAK,CAAA;AAAA,EAC/B;AACA,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AAEnB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,CAAC,SAAS,GAAG,SAAS,IAAI,IAAA,CAAK,UAAA,CAAW,MAAM,GAAG,CAAA;AACzD,IAAA,IAAI,EAAE,WAAW,MAAA,CAAA,EAAS;AAC1B,IAAA,MAAA,CAAO,OAAO,CAAA,GAAI,SAAA,CAAU,MAAA,CAAO,OAAO,CAAA,EAAG,SAAA,EAAW,IAAA,CAAK,WAAA,EAAa,IAAA,CAAK,IAAA,IAAQ,SAAS,CAAA;AAAA,EAClG;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,oBAAoB,IAAA,EAA4C;AAC9E,EAAA,IAAI,CAAC,aAAA,CAAc,IAAI,CAAA,EAAG,OAAO,MAAA;AACjC,EAAA,MAAM,QAAQ,IAAA,CAAK,iBAAA;AACnB,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAK,KAAA,GAAqC,MAAA;AACtE;;;AClEO,IAAM,sBAAN,MAAmD;AAAA,EACvC,GAAA,uBAAU,GAAA,EAA6B;AAAA,EAExD,GAAA,CAAI,KAAa,KAAA,EAA8B;AAC7C,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EACzB;AAAA,EACA,IAAI,GAAA,EAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAAA,EACzB;AAAA,EACA,IAAA,GAAiB;AACf,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAAA,EAC5B;AAAA,EACA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AAAA,EACjB;AACF;AAMO,IAAM,4BAAN,MAAyD;AAAA,EAC7C,KAAA;AAAA,EAEjB,WAAA,CAAY,SAAS,OAAA,EAAS;AAC5B,IAAA,IAAA,CAAK,KAAA,GAAQ,GAAG,MAAM,CAAA,UAAA,CAAA;AAAA,EACxB;AAAA,EAEQ,IAAA,GAAwC;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AAC3C,MAAA,OAAO,GAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,IAAwC,EAAC;AAAA,IACvE,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,MAAM,IAAA,EAA6C;AACzD,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,QAAQ,IAAA,CAAK,KAAA,EAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,IACvD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,GAAA,CAAI,KAAa,KAAA,EAA8B;AAC7C,IAAA,MAAM,IAAA,GAAO,KAAK,IAAA,EAAK;AACvB,IAAA,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AACZ,IAAA,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACjB;AAAA,EACA,IAAI,GAAA,EAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,IAAA,EAAK,CAAE,GAAG,CAAA;AAAA,EACxB;AAAA,EACA,IAAA,GAAiB;AACf,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,CAAA;AAAA,EAChC;AAAA,EACA,KAAA,GAAc;AACZ,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,UAAA,CAAW,KAAK,KAAK,CAAA;AAAA,IACpC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACF","file":"chunk-TLTG3BTC.js","sourcesContent":["import type { JsonValue } from \"./types\";\n\n/**\n * A single content swap, as emitted in a webhook-response body's\n * `xeniaContentSwaps` array (the multi-slot personalization analogue of\n * `xeniaActions`). `identifier` is `\"<slotKey>\"` (whole-slot replace) or\n * `\"<slotKey>.<dotted.path>\"` addressing a node inside that slot's JSON\n * (object keys or array indices).\n *\n * NOTE: this field name/shape is a proposed contract, not yet emitted by any\n * journey node — confirm with the Journey Orchestrator (FE/BE) team before\n * relying on it in production.\n */\nexport interface ContentSwap {\n identifier: string;\n replacement: JsonValue;\n /** `\"replace\"` (default) swaps the whole matched node; `\"merge\"` shallow-merges when both sides are objects. */\n mode?: \"replace\" | \"merge\";\n}\n\nfunction isPlainObject(v: JsonValue): v is { [key: string]: JsonValue } {\n return v !== null && typeof v === \"object\" && !Array.isArray(v);\n}\n\nfunction cloneJson<T extends JsonValue>(value: T): T {\n return value === null || typeof value !== \"object\" ? value : (JSON.parse(JSON.stringify(value)) as T);\n}\n\nfunction setAtPath(node: JsonValue, path: string[], value: JsonValue, mode: \"replace\" | \"merge\"): JsonValue {\n if (path.length === 0) {\n if (mode === \"merge\" && isPlainObject(node) && isPlainObject(value)) {\n return { ...node, ...value };\n }\n return value;\n }\n\n const [key, ...rest] = path;\n if (Array.isArray(node)) {\n const index = Number(key);\n if (!Number.isInteger(index) || index < 0 || index >= node.length) return node;\n const next = node.slice();\n next[index] = setAtPath(next[index], rest, value, mode);\n return next;\n }\n if (isPlainObject(node)) {\n if (!(key in node)) return node;\n return { ...node, [key]: setAtPath(node[key], rest, value, mode) };\n }\n return node;\n}\n\n/**\n * Splice `swaps` into a base map of named content slots, recursively at any\n * nesting depth. Defensive by design (mirrors the PHP SDK's personalization\n * client): a swap whose `identifier` doesn't resolve to an existing slot/path\n * is silently ignored rather than thrown — this never fails, it degrades to\n * the base slot value. Slots are deep-cloned; inputs are never mutated.\n */\nexport function spliceSlots(\n slots: Record<string, JsonValue>,\n swaps: ContentSwap[] | undefined,\n): Record<string, JsonValue> {\n const result: Record<string, JsonValue> = {};\n for (const [key, value] of Object.entries(slots)) {\n result[key] = cloneJson(value);\n }\n if (!swaps) return result;\n\n for (const swap of swaps) {\n const [slotKey, ...pathParts] = swap.identifier.split(\".\");\n if (!(slotKey in result)) continue;\n result[slotKey] = setAtPath(result[slotKey], pathParts, swap.replacement, swap.mode ?? \"replace\");\n }\n return result;\n}\n\n/** Extract `xeniaContentSwaps` from a webhook-response body, if present and well-formed. */\nexport function extractContentSwaps(body: JsonValue): ContentSwap[] | undefined {\n if (!isPlainObject(body)) return undefined;\n const swaps = body.xeniaContentSwaps;\n return Array.isArray(swaps) ? (swaps as unknown as ContentSwap[]) : undefined;\n}\n","import type { WebhookResponse } from \"./types\";\n\n/**\n * Persists webhook responses the SDK receives, keyed by an arbitrary string\n * (typically the eventId, triggerId, or journeyId). Lets the app read back the\n * last server response for a given interaction without re-firing it.\n */\nexport interface ResponseStore {\n set(key: string, value: WebhookResponse): void;\n get(key: string): WebhookResponse | undefined;\n keys(): string[];\n clear(): void;\n}\n\n/** In-memory store. Default; lost on reload. */\nexport class MemoryResponseStore implements ResponseStore {\n private readonly map = new Map<string, WebhookResponse>();\n\n set(key: string, value: WebhookResponse): void {\n this.map.set(key, value);\n }\n get(key: string): WebhookResponse | undefined {\n return this.map.get(key);\n }\n keys(): string[] {\n return [...this.map.keys()];\n }\n clear(): void {\n this.map.clear();\n }\n}\n\n/**\n * localStorage-backed store — survives reloads. Falls back to memory semantics\n * (silent no-op reads/writes) when localStorage is unavailable or throws.\n */\nexport class LocalStorageResponseStore implements ResponseStore {\n private readonly nsKey: string;\n\n constructor(prefix = \"xenia\") {\n this.nsKey = `${prefix}_responses`;\n }\n\n private read(): Record<string, WebhookResponse> {\n try {\n const raw = localStorage.getItem(this.nsKey);\n return raw ? (JSON.parse(raw) as Record<string, WebhookResponse>) : {};\n } catch {\n return {};\n }\n }\n\n private write(data: Record<string, WebhookResponse>): void {\n try {\n localStorage.setItem(this.nsKey, JSON.stringify(data));\n } catch {\n /* storage full / unavailable — ignore */\n }\n }\n\n set(key: string, value: WebhookResponse): void {\n const data = this.read();\n data[key] = value;\n this.write(data);\n }\n get(key: string): WebhookResponse | undefined {\n return this.read()[key];\n }\n keys(): string[] {\n return Object.keys(this.read());\n }\n clear(): void {\n try {\n localStorage.removeItem(this.nsKey);\n } catch {\n /* ignore */\n }\n }\n}\n"]}
@@ -163,12 +163,22 @@ var HttpError = class extends Error {
163
163
  status;
164
164
  data;
165
165
  };
166
+ var CircuitOpenError = class extends Error {
167
+ constructor(endpoint) {
168
+ super(`Circuit open for ${endpoint}: failing fast until the cooldown passes`);
169
+ this.endpoint = endpoint;
170
+ this.name = "CircuitOpenError";
171
+ }
172
+ endpoint;
173
+ };
174
+ var breakers = /* @__PURE__ */ new Map();
166
175
  var HttpClient = class {
167
176
  baseUrl;
168
177
  defaultHeaders;
169
178
  timeout;
170
179
  retry;
171
180
  debug;
181
+ breaker;
172
182
  constructor(opts) {
173
183
  this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
174
184
  this.defaultHeaders = opts.defaultHeaders ?? {};
@@ -178,8 +188,37 @@ var HttpClient = class {
178
188
  baseDelayMs: opts.retry?.baseDelayMs ?? 300
179
189
  };
180
190
  this.debug = opts.debug ?? false;
191
+ const cb = opts.circuitBreaker === true ? {} : opts.circuitBreaker || null;
192
+ this.breaker = cb && { failureThreshold: cb.failureThreshold ?? 3, cooldownMs: cb.cooldownMs ?? 3e4 };
181
193
  }
182
194
  async request(opts) {
195
+ if (!this.breaker) return this.send(opts);
196
+ const key = buildUrl(this.baseUrl + opts.path, opts.query);
197
+ const b = breakers.get(key) ?? { failures: 0, openedAt: 0 };
198
+ if (b.openedAt) {
199
+ if (Date.now() - b.openedAt < this.breaker.cooldownMs) throw new CircuitOpenError(key);
200
+ b.openedAt = 0;
201
+ b.failures = this.breaker.failureThreshold - 1;
202
+ }
203
+ try {
204
+ const result = await this.send(opts);
205
+ breakers.delete(key);
206
+ return result;
207
+ } catch (err) {
208
+ if (err instanceof HttpError && !this.isRetryableStatus(err.status)) {
209
+ breakers.delete(key);
210
+ throw err;
211
+ }
212
+ b.failures += 1;
213
+ if (b.failures >= this.breaker.failureThreshold) {
214
+ b.openedAt = Date.now();
215
+ this.log(`circuit opened for ${opts.path} after ${b.failures} failures`);
216
+ }
217
+ breakers.set(key, b);
218
+ throw err;
219
+ }
220
+ }
221
+ async send(opts) {
183
222
  const url = buildUrl(this.baseUrl + opts.path, opts.query);
184
223
  const method = opts.method ?? "GET";
185
224
  const headers = {
@@ -332,6 +371,7 @@ var XeniaApi = class {
332
371
  defaultHeaders: config.headers,
333
372
  timeout: config.timeout,
334
373
  retry: config.retry,
374
+ circuitBreaker: config.circuitBreaker,
335
375
  debug: config.debug
336
376
  });
337
377
  }
@@ -504,6 +544,18 @@ var XeniaApi = class {
504
544
  }
505
545
  };
506
546
 
547
+ // src/core/cookie-names.ts
548
+ var DEFAULT_PREFIX = "xenia";
549
+ function visitorCookieName(prefix = DEFAULT_PREFIX) {
550
+ return `${prefix || DEFAULT_PREFIX}_vid`;
551
+ }
552
+ function consentCookieName(prefix = DEFAULT_PREFIX) {
553
+ return `${prefix || DEFAULT_PREFIX}_consent`;
554
+ }
555
+ function consentCookie(state, prefix, maxAgeDays = 365) {
556
+ return `${consentCookieName(prefix)}=${encodeURIComponent(JSON.stringify(state))}; path=/; max-age=${Math.floor(maxAgeDays * 86400)}; SameSite=Lax`;
557
+ }
558
+
507
559
  // src/core/event-payload.ts
508
560
  var RESERVED = /* @__PURE__ */ new Set([
509
561
  "eventId",
@@ -933,12 +985,6 @@ var AutoTracker = class {
933
985
  }
934
986
  };
935
987
 
936
- // src/core/cookie-names.ts
937
- var DEFAULT_PREFIX = "xenia";
938
- function visitorCookieName(prefix = DEFAULT_PREFIX) {
939
- return `${prefix || DEFAULT_PREFIX}_vid`;
940
- }
941
-
942
988
  // src/client/identity.ts
943
989
  var SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
944
990
  var Identity = class {
@@ -2216,6 +2262,12 @@ var XeniaClient = class {
2216
2262
  async consent(state) {
2217
2263
  const wasAllowed = this.analyticsAllowed();
2218
2264
  this.consentState = { ...this.consentState, ...state };
2265
+ if (isBrowser()) {
2266
+ try {
2267
+ document.cookie = consentCookie(this.consentState, this.options.prefix);
2268
+ } catch {
2269
+ }
2270
+ }
2219
2271
  if (this.analyticsAllowed() && !wasAllowed) {
2220
2272
  this.analyticsQueue.start();
2221
2273
  void this.analyticsQueue.flush();
@@ -2314,6 +2366,8 @@ exports.WIDGET_RENDERERS = WIDGET_RENDERERS;
2314
2366
  exports.XeniaClient = XeniaClient;
2315
2367
  exports.collectFields = collectFields;
2316
2368
  exports.computeSpinRotation = computeSpinRotation;
2369
+ exports.consentCookie = consentCookie;
2370
+ exports.consentCookieName = consentCookieName;
2317
2371
  exports.createXeniaClient = createXeniaClient;
2318
2372
  exports.extractContentSwaps = extractContentSwaps;
2319
2373
  exports.hideContent = hideContent;