@xenia-martech/sdk-js 1.2.0-dev.1 → 1.2.0-dev.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +6 -1
  2. package/dist/{actions-D9_aAvCv.d.cts → actions-Bhji05Pe.d.cts} +19 -4
  3. package/dist/{actions-D9_aAvCv.d.ts → actions-Bhji05Pe.d.ts} +19 -4
  4. package/dist/{api-CktVQ6Gl.d.ts → api-BqSvWgBZ.d.cts} +4 -2
  5. package/dist/{api-BEPW0Uan.d.cts → api-ByoECRhR.d.ts} +4 -2
  6. package/dist/{chunk-DWFVDNU5.js → chunk-INM2SPH4.js} +4 -4
  7. package/dist/chunk-INM2SPH4.js.map +1 -0
  8. package/dist/{chunk-7NGJC7CF.js → chunk-TGG5Y4QD.js} +17 -6
  9. package/dist/chunk-TGG5Y4QD.js.map +1 -0
  10. package/dist/{chunk-3PYPPIUM.cjs → chunk-TRRMMPBH.cjs} +13 -13
  11. package/dist/chunk-TRRMMPBH.cjs.map +1 -0
  12. package/dist/{chunk-IBNIRT7J.cjs → chunk-YZG6JR4E.cjs} +17 -6
  13. package/dist/chunk-YZG6JR4E.cjs.map +1 -0
  14. package/dist/client/index.cjs +43 -8
  15. package/dist/client/index.cjs.map +1 -1
  16. package/dist/client/index.d.cts +2 -2
  17. package/dist/client/index.d.ts +2 -2
  18. package/dist/client/index.js +43 -8
  19. package/dist/client/index.js.map +1 -1
  20. package/dist/client/react/index.cjs +46 -11
  21. package/dist/client/react/index.cjs.map +1 -1
  22. package/dist/client/react/index.d.cts +2 -2
  23. package/dist/client/react/index.d.ts +2 -2
  24. package/dist/client/react/index.js +46 -11
  25. package/dist/client/react/index.js.map +1 -1
  26. package/dist/cms/contentful.cjs +2 -1
  27. package/dist/cms/contentful.cjs.map +1 -1
  28. package/dist/cms/contentful.d.cts +1 -1
  29. package/dist/cms/contentful.d.ts +1 -1
  30. package/dist/cms/contentful.js +2 -1
  31. package/dist/cms/contentful.js.map +1 -1
  32. package/dist/{cookie-names-CLqtmGBM.d.ts → cookie-names-Bxd-VNyJ.d.ts} +1 -1
  33. package/dist/{cookie-names-BACctagz.d.cts → cookie-names-RXVfGYPE.d.cts} +1 -1
  34. package/dist/index.cjs +21 -21
  35. package/dist/index.d.cts +4 -4
  36. package/dist/index.d.ts +4 -4
  37. package/dist/index.js +1 -1
  38. package/dist/next/index.cjs +9 -9
  39. package/dist/next/index.d.cts +3 -3
  40. package/dist/next/index.d.ts +3 -3
  41. package/dist/next/index.js +2 -2
  42. package/dist/{personalize-content-Clc1oMYY.d.cts → personalize-content-Bf6YZdkZ.d.cts} +12 -1
  43. package/dist/{personalize-content-Clc1oMYY.d.ts → personalize-content-Bf6YZdkZ.d.ts} +12 -1
  44. package/dist/server/index.cjs +19 -19
  45. package/dist/server/index.d.cts +5 -5
  46. package/dist/server/index.d.ts +5 -5
  47. package/dist/server/index.js +3 -3
  48. package/dist/xenia-sdk.iife.js +3 -3
  49. package/dist/xenia-sdk.iife.js.map +1 -1
  50. package/dist/{xenia-server-BWhWD0La.d.ts → xenia-server-CcjQenru.d.ts} +2 -2
  51. package/dist/{xenia-server-o_wDOcei.d.cts → xenia-server-MlI3Khya.d.cts} +2 -2
  52. package/package.json +1 -1
  53. package/dist/chunk-3PYPPIUM.cjs.map +0 -1
  54. package/dist/chunk-7NGJC7CF.js.map +0 -1
  55. package/dist/chunk-DWFVDNU5.js.map +0 -1
  56. package/dist/chunk-IBNIRT7J.cjs.map +0 -1
@@ -555,7 +555,7 @@ var XeniaApi = class {
555
555
  * ({@link personalizeContent}) calls this once per round with the runtime
556
556
  * targets it found; callers rarely need it directly.
557
557
  */
558
- async resolveEntries(entryIds, opts = {}) {
558
+ async resolveEntries(entryIds, opts) {
559
559
  const { data } = await this.http.request({
560
560
  method: "POST",
561
561
  path: "/api/personalization/resolve-entries",
@@ -563,7 +563,8 @@ var XeniaApi = class {
563
563
  body: compact({
564
564
  entryIds,
565
565
  data: opts.data,
566
- locale: opts.locale
566
+ locale: opts.locale,
567
+ contentKey: opts.contentKey
567
568
  })
568
569
  });
569
570
  return data;
@@ -687,7 +688,7 @@ var DEFAULT_TIMEOUT_MS = 300;
687
688
  var DEFAULT_MAX_ROUNDS = 3;
688
689
  var copyOf = (v) => v && typeof v === "object" && typeof structuredClone === "function" ? structuredClone(v) : v;
689
690
  async function personalizeContent(payload, options) {
690
- const { cms } = options;
691
+ const cms = scopedAdapter(options.cms, options.contentKey);
691
692
  const maxRounds = options.maxRounds ?? DEFAULT_MAX_ROUNDS;
692
693
  const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
693
694
  const applied = [];
@@ -886,7 +887,8 @@ function withDeadline(promise, deadline) {
886
887
  })
887
888
  ]).finally(() => clearTimeout(timer));
888
889
  }
889
- function pendingTargets(payload, cms) {
890
+ function pendingTargets(payload, adapter, contentKey) {
891
+ const cms = scopedAdapter(adapter, contentKey);
890
892
  try {
891
893
  let content = typeof structuredClone === "function" ? structuredClone(payload) : payload;
892
894
  content = cms.prepare ? cms.prepare(content) : content;
@@ -897,6 +899,15 @@ function pendingTargets(payload, cms) {
897
899
  return [];
898
900
  }
899
901
  }
902
+ function scopedAdapter(cms, contentKey) {
903
+ return {
904
+ ...cms,
905
+ marker(entry) {
906
+ const m = cms.marker(entry);
907
+ return m && contentKey && m.keys?.includes(contentKey) ? m : null;
908
+ }
909
+ };
910
+ }
900
911
  async function personalizePage(ref, options) {
901
912
  let page;
902
913
  try {
@@ -1238,6 +1249,20 @@ var AutoTracker = class {
1238
1249
  }
1239
1250
  };
1240
1251
 
1252
+ // src/server/cookies.ts
1253
+ function parseCookies(header) {
1254
+ const out = {};
1255
+ if (!header) return out;
1256
+ for (const part of header.split(";")) {
1257
+ const idx = part.indexOf("=");
1258
+ if (idx === -1) continue;
1259
+ const key = part.slice(0, idx).trim();
1260
+ const value = part.slice(idx + 1).trim();
1261
+ if (key) out[key] = decodeURIComponent(value);
1262
+ }
1263
+ return out;
1264
+ }
1265
+
1241
1266
  // src/client/identity.ts
1242
1267
  var SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
1243
1268
  var Identity = class {
@@ -1285,10 +1310,19 @@ var Identity = class {
1285
1310
  } catch {
1286
1311
  }
1287
1312
  }
1313
+ /** The visitor id already in the cookie — e.g. minted by `xeniaProxy()` on the first request. */
1314
+ readVisitorCookie() {
1315
+ if (!this.cookie || typeof document === "undefined") return null;
1316
+ try {
1317
+ return parseCookies(document.cookie)[this.cookieName()] || null;
1318
+ } catch {
1319
+ return null;
1320
+ }
1321
+ }
1288
1322
  // ── Device id ────────────────────────────────────────────────────────────
1289
1323
  /**
1290
- * Resolve a stable device id: localStorage cache → MediaDevices → SHA-256
1291
- * browser fingerprint. Cached for the session and across reloads.
1324
+ * Resolve a stable device id: localStorage cache → the visitor cookie a server already set →
1325
+ * MediaDevices → SHA-256 browser fingerprint. Cached for the session and across reloads.
1292
1326
  */
1293
1327
  async resolveDeviceId() {
1294
1328
  if (this.deviceId) {
@@ -1305,7 +1339,8 @@ var Identity = class {
1305
1339
  }
1306
1340
  } catch {
1307
1341
  }
1308
- let id = await this.mediaDeviceId();
1342
+ let id = this.readVisitorCookie();
1343
+ if (!id) id = await this.mediaDeviceId();
1309
1344
  if (!id) id = await this.fingerprint();
1310
1345
  this.deviceId = id;
1311
1346
  try {
@@ -2384,7 +2419,7 @@ var XeniaClient = class {
2384
2419
  return personalizePage(ref, { ...opts, resolve: this.entryResolver(opts) });
2385
2420
  }
2386
2421
  entryResolver(opts) {
2387
- const resolveOpts = this.withVisitor({ data: opts.data, locale: opts.locale });
2422
+ const resolveOpts = { ...this.withVisitor({ data: opts.data, locale: opts.locale }), contentKey: opts.contentKey };
2388
2423
  return async (ids) => (await this.api.resolveEntries(ids, resolveOpts)).decisions ?? [];
2389
2424
  }
2390
2425
  /** The SDK-owned visitor anchor: the `identify()`/`config.visitorId` id, else the device id. */
@@ -2801,8 +2836,8 @@ function usePersonalizedContent(page, opts) {
2801
2836
  const xenia = useXenia();
2802
2837
  const hide = opts.render === "hide-until-resolved";
2803
2838
  const initialPending = react.useMemo(
2804
- () => new Set(page == null ? [] : pendingTargets(page, opts.cms)),
2805
- [page]
2839
+ () => new Set(page == null ? [] : pendingTargets(page, opts.cms, opts.contentKey)),
2840
+ [page, opts.contentKey]
2806
2841
  // markers live in `page`; a new adapter object for the same page changes nothing
2807
2842
  );
2808
2843
  const [state, setState] = react.useState(
@@ -2810,7 +2845,7 @@ function usePersonalizedContent(page, opts) {
2810
2845
  );
2811
2846
  const optsRef = react.useRef(opts);
2812
2847
  optsRef.current = opts;
2813
- const optsKey = JSON.stringify({ data: opts.data ?? {}, locale: opts.locale });
2848
+ const optsKey = JSON.stringify({ data: opts.data ?? {}, locale: opts.locale, contentKey: opts.contentKey });
2814
2849
  react.useEffect(() => {
2815
2850
  if (page == null) return;
2816
2851
  let active = true;