@xenia-martech/sdk-js 1.2.0-dev.7 → 1.2.0-dev.9

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 (96) hide show
  1. package/README.md +70 -6
  2. package/dist/{actions-35V37IT0.d.cts → actions--1_9Z8ig.d.cts} +13 -2
  3. package/dist/{actions-35V37IT0.d.ts → actions--1_9Z8ig.d.ts} +13 -2
  4. package/dist/{api-0IycTYJR.d.cts → api-DbUxT38T.d.ts} +1 -1
  5. package/dist/{api-COXWLL5L.d.ts → api-DgzJ5s-k.d.cts} +1 -1
  6. package/dist/chunk-DPXINHQR.cjs +34 -0
  7. package/dist/chunk-DPXINHQR.cjs.map +1 -0
  8. package/dist/chunk-FSJMHXS6.js +432 -0
  9. package/dist/chunk-FSJMHXS6.js.map +1 -0
  10. package/dist/chunk-GXJLU3RE.cjs +448 -0
  11. package/dist/chunk-GXJLU3RE.cjs.map +1 -0
  12. package/dist/{chunk-2DR5AVPX.cjs → chunk-I5EHLRSR.cjs} +11 -10
  13. package/dist/chunk-I5EHLRSR.cjs.map +1 -0
  14. package/dist/{chunk-LW5AEJ6K.js → chunk-MEULT5X6.js} +4 -241
  15. package/dist/chunk-MEULT5X6.js.map +1 -0
  16. package/dist/{chunk-GWRDZIVA.js → chunk-NDRRSRTU.js} +4 -3
  17. package/dist/chunk-NDRRSRTU.js.map +1 -0
  18. package/dist/chunk-RC46KXDM.js +32 -0
  19. package/dist/chunk-RC46KXDM.js.map +1 -0
  20. package/dist/{chunk-RWE2OCQL.cjs → chunk-SU25SELD.cjs} +4 -244
  21. package/dist/chunk-SU25SELD.cjs.map +1 -0
  22. package/dist/{chunk-WHGK55JP.cjs → chunk-UUIKUU5W.cjs} +5 -5
  23. package/dist/{chunk-WHGK55JP.cjs.map → chunk-UUIKUU5W.cjs.map} +1 -1
  24. package/dist/{chunk-QEYONKWY.js → chunk-UVTFGQR6.js} +3 -3
  25. package/dist/{chunk-QEYONKWY.js.map → chunk-UVTFGQR6.js.map} +1 -1
  26. package/dist/{chunk-OMMIRSPK.js → chunk-V4EGU3PM.js} +48 -11
  27. package/dist/chunk-V4EGU3PM.js.map +1 -0
  28. package/dist/{chunk-YLMMTKQL.cjs → chunk-WMGCQPHY.cjs} +52 -13
  29. package/dist/chunk-WMGCQPHY.cjs.map +1 -0
  30. package/dist/client/index.cjs +26 -10
  31. package/dist/client/index.cjs.map +1 -1
  32. package/dist/client/index.d.cts +2 -2
  33. package/dist/client/index.d.ts +2 -2
  34. package/dist/client/index.js +26 -10
  35. package/dist/client/index.js.map +1 -1
  36. package/dist/client/react/index.cjs +73 -15
  37. package/dist/client/react/index.cjs.map +1 -1
  38. package/dist/client/react/index.d.cts +9 -3
  39. package/dist/client/react/index.d.ts +9 -3
  40. package/dist/client/react/index.js +73 -15
  41. package/dist/client/react/index.js.map +1 -1
  42. package/dist/cms/contentful.cjs +7 -24
  43. package/dist/cms/contentful.cjs.map +1 -1
  44. package/dist/cms/contentful.d.cts +5 -4
  45. package/dist/cms/contentful.d.ts +5 -4
  46. package/dist/cms/contentful.js +4 -23
  47. package/dist/cms/contentful.js.map +1 -1
  48. package/dist/cms/contentstack.cjs +120 -0
  49. package/dist/cms/contentstack.cjs.map +1 -0
  50. package/dist/cms/contentstack.d.cts +41 -0
  51. package/dist/cms/contentstack.d.ts +41 -0
  52. package/dist/cms/contentstack.js +117 -0
  53. package/dist/cms/contentstack.js.map +1 -0
  54. package/dist/{consent-DRCV0N0d.d.ts → consent-Dtiqzz2B.d.cts} +71 -11
  55. package/dist/{consent-BgAETCkL.d.cts → consent-byYiDMFr.d.ts} +71 -11
  56. package/dist/{cookie-names-DU3MtcNG.d.ts → cookie-names-B4hda2rX.d.cts} +1 -1
  57. package/dist/{cookie-names-DFItnSLK.d.cts → cookie-names-DioZXuV0.d.ts} +1 -1
  58. package/dist/edge/index.cjs +122 -29
  59. package/dist/edge/index.cjs.map +1 -1
  60. package/dist/edge/index.d.cts +42 -6
  61. package/dist/edge/index.d.ts +42 -6
  62. package/dist/edge/index.js +92 -9
  63. package/dist/edge/index.js.map +1 -1
  64. package/dist/index.cjs +31 -31
  65. package/dist/index.d.cts +4 -5
  66. package/dist/index.d.ts +4 -5
  67. package/dist/index.js +2 -2
  68. package/dist/next/index.cjs +39 -34
  69. package/dist/next/index.cjs.map +1 -1
  70. package/dist/next/index.d.cts +2 -3
  71. package/dist/next/index.d.ts +2 -3
  72. package/dist/next/index.js +13 -8
  73. package/dist/next/index.js.map +1 -1
  74. package/dist/{types-DgVHS4Qw.d.ts → personalize-content-D6xeBI7-.d.cts} +150 -1
  75. package/dist/{types-DgVHS4Qw.d.cts → personalize-content-D6xeBI7-.d.ts} +150 -1
  76. package/dist/server/index.cjs +30 -30
  77. package/dist/server/index.d.cts +5 -6
  78. package/dist/server/index.d.ts +5 -6
  79. package/dist/server/index.js +5 -5
  80. package/dist/xenia-sdk.iife.js +3 -3
  81. package/dist/xenia-sdk.iife.js.map +1 -1
  82. package/dist/{xenia-server-Cf24mL0c.d.ts → xenia-server-BcgeUHX4.d.ts} +2 -3
  83. package/dist/{xenia-server-D-bx14lw.d.cts → xenia-server-lv6LtJZP.d.cts} +2 -3
  84. package/package.json +14 -1
  85. package/dist/chunk-2DR5AVPX.cjs.map +0 -1
  86. package/dist/chunk-BQ5PJCZ7.js +0 -179
  87. package/dist/chunk-BQ5PJCZ7.js.map +0 -1
  88. package/dist/chunk-GWRDZIVA.js.map +0 -1
  89. package/dist/chunk-LW5AEJ6K.js.map +0 -1
  90. package/dist/chunk-N5M4PI7C.cjs +0 -192
  91. package/dist/chunk-N5M4PI7C.cjs.map +0 -1
  92. package/dist/chunk-OMMIRSPK.js.map +0 -1
  93. package/dist/chunk-RWE2OCQL.cjs.map +0 -1
  94. package/dist/chunk-YLMMTKQL.cjs.map +0 -1
  95. package/dist/personalize-content-Cwc2AomC.d.ts +0 -141
  96. package/dist/personalize-content-CxSdplMV.d.cts +0 -141
@@ -722,7 +722,7 @@ async function personalizeContent(payload, options) {
722
722
  const next = apply(target, op, d.decision.field ?? target.marker.field, items, cms);
723
723
  report({
724
724
  target: target.id,
725
- kind: "runtime",
725
+ kind: target.local ? "static" : "runtime",
726
726
  op,
727
727
  entryIds: items.map((e) => cms.entryId(e)).filter((id) => !!id),
728
728
  contentKey: d.decision.contentKey,
@@ -732,20 +732,23 @@ async function personalizeContent(payload, options) {
732
732
  return next;
733
733
  };
734
734
  for (let round = 0; ; round++) {
735
- const pending = walk(frontier, cms, settled, round, report, (t) => {
735
+ const pending = walk(frontier, cms, settled, round, report, options.contentKey, (t) => {
736
736
  const d = decided.get(t.id);
737
737
  return d ? settle(t, d, round) : void 0;
738
738
  });
739
739
  if (pending.size === 0) return { content: box.root, applied, complete: true };
740
- if (!options.resolve || round >= maxRounds) {
741
- return { content: box.root, applied, complete: !options.resolve };
740
+ const remote = [...pending.values()].filter((p) => !p.local).map((p) => p.id);
741
+ const local = [...pending.values()].flatMap((p) => p.local ? [p.local] : []);
742
+ if (!options.resolve && local.length === 0 || round >= maxRounds) {
743
+ return { content: box.root, applied, complete: !options.resolve && round < maxRounds };
742
744
  }
743
745
  progress(options, { content: box.root, round, pending: [...pending.keys()] });
744
746
  let decisions;
745
747
  let entriesById;
746
748
  let queried;
747
749
  try {
748
- decisions = await withDeadline(options.resolve([...pending.keys()]), deadline);
750
+ decisions = options.resolve && remote.length > 0 ? await withDeadline(options.resolve(remote), deadline) : [];
751
+ decisions = [...decisions, ...local];
749
752
  ({ entriesById, queried } = await withDeadline(loadReplacements(decisions, cms, options.locale), deadline));
750
753
  } catch (error) {
751
754
  return { content: box.root, applied, complete: false, error: error === TIMEOUT ? void 0 : error };
@@ -768,7 +771,7 @@ function progress(options, p) {
768
771
  } catch {
769
772
  }
770
773
  }
771
- function walk(frontier, cms, settled, round, report, reuse) {
774
+ function walk(frontier, cms, settled, round, report, contentKey, reuse) {
772
775
  const pending = /* @__PURE__ */ new Map();
773
776
  const seen = /* @__PURE__ */ new WeakSet();
774
777
  const deferred = /* @__PURE__ */ new WeakSet();
@@ -779,7 +782,8 @@ function walk(frontier, cms, settled, round, report, reuse) {
779
782
  if (!value || typeof value !== "object" || deferred.has(value)) continue;
780
783
  const id = settled.has(value) ? void 0 : cms.entryId(value);
781
784
  const marker = id ? cms.marker(value) : null;
782
- if (id && marker?.kind === "runtime") {
785
+ const local = id && marker?.kind === "static" && marker.ids?.length && cms.staticVariants(value).length === 0 ? localDecision(id, marker, contentKey) : void 0;
786
+ if (id && marker && (marker.kind === "runtime" || local)) {
783
787
  const again = reuse({ id, marker, entry: value, slots: [slot] });
784
788
  if (again) {
785
789
  queue.push(...again);
@@ -789,7 +793,7 @@ function walk(frontier, cms, settled, round, report, reuse) {
789
793
  if (existing) {
790
794
  existing.slots.push(slot);
791
795
  } else {
792
- pending.set(id, { id, marker, entry: value, slots: [slot] });
796
+ pending.set(id, { id, marker, entry: value, slots: [slot], ...local ? { local } : {} });
793
797
  if (marker.op === "items" && marker.field) {
794
798
  const held = cms.getField(value, marker.field);
795
799
  if (held && typeof held === "object") deferred.add(held);
@@ -823,6 +827,16 @@ function walk(frontier, cms, settled, round, report, reuse) {
823
827
  }
824
828
  return pending;
825
829
  }
830
+ function localDecision(id, marker, contentKey) {
831
+ return {
832
+ target: id,
833
+ op: marker.op ?? "replace",
834
+ ...marker.field ? { field: marker.field } : {},
835
+ ids: marker.ids,
836
+ ...marker.ct ? { contentType: marker.ct } : {},
837
+ contentKey
838
+ };
839
+ }
826
840
  function apply(target, op, field, items, cms) {
827
841
  if (op === "items") {
828
842
  if (field) {
@@ -861,9 +875,11 @@ function children(value) {
861
875
  }
862
876
  async function loadReplacements(decisions, cms, locale) {
863
877
  const ids = [...new Set(decisions.flatMap((d) => d.ids ?? []))];
878
+ const types = {};
879
+ for (const d of decisions) if (d.contentType) for (const id of d.ids ?? []) types[id] = d.contentType;
864
880
  const queries = decisions.filter((d) => !d.ids && d.query);
865
881
  const [fetched, ...results] = await Promise.all([
866
- ids.length > 0 ? cms.fetchEntries(ids, locale) : Promise.resolve([]),
882
+ ids.length > 0 ? cms.fetchEntries(ids, locale, types) : Promise.resolve([]),
867
883
  ...queries.map((d) => cms.queryEntries(d.query, locale).catch(() => []))
868
884
  ]);
869
885
  const entriesById = /* @__PURE__ */ new Map();
@@ -894,7 +910,7 @@ function pendingTargets(payload, adapter, contentKey) {
894
910
  content = cms.prepare ? cms.prepare(content) : content;
895
911
  const root = { parent: { root: content }, key: "root", value: content };
896
912
  return [...walk([root], cms, /* @__PURE__ */ new WeakSet(), 0, () => {
897
- }, () => void 0).keys()];
913
+ }, contentKey, () => void 0).keys()];
898
914
  } catch {
899
915
  return [];
900
916
  }
@@ -3332,6 +3348,7 @@ function readEntry(prefix) {
3332
3348
  return readDebugEntries(raw)[location.pathname] ?? null;
3333
3349
  }
3334
3350
  var OPEN_KEY = "xenia_debug_open";
3351
+ var PIN_KEY = "xenia_debug_pinned";
3335
3352
  var TAB_KEY = "xenia_debug_tab";
3336
3353
  function Mark({ size }) {
3337
3354
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 32 20", "aria-hidden": "true", focusable: "false", children: [
@@ -3346,9 +3363,16 @@ function Id({ value }) {
3346
3363
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value });
3347
3364
  }
3348
3365
  var percent = (n) => `${Math.round(n <= 1 ? n * 100 : n)}%`;
3349
- function XeniaDebugPanel({ prefix = DEFAULT_PREFIX, position = "bottom-right", defaultOpen = false, renderExtra }) {
3366
+ function XeniaDebugPanel({
3367
+ prefix = DEFAULT_PREFIX,
3368
+ position = "bottom-right",
3369
+ defaultOpen = false,
3370
+ keepOpen = false,
3371
+ renderExtra
3372
+ }) {
3350
3373
  const [entry, setEntry] = react.useState(null);
3351
3374
  const [open, setOpen] = react.useState(false);
3375
+ const [pinned, setPinned] = react.useState(keepOpen);
3352
3376
  const [tab, setTab] = react.useState("Decision");
3353
3377
  const root = react.useRef(null);
3354
3378
  const launcher = react.useRef(null);
@@ -3368,31 +3392,39 @@ function XeniaDebugPanel({ prefix = DEFAULT_PREFIX, position = "bottom-right", d
3368
3392
  try {
3369
3393
  const saved = sessionStorage.getItem(OPEN_KEY);
3370
3394
  setOpen(saved === null ? defaultOpen : saved === "1");
3395
+ const savedPin = sessionStorage.getItem(PIN_KEY);
3396
+ setPinned(savedPin === null ? keepOpen : savedPin === "1");
3371
3397
  const savedTab = sessionStorage.getItem(TAB_KEY);
3372
3398
  if (savedTab === "Decision" || savedTab === "Visitor" || savedTab === "Request" || savedTab === "Site") setTab(savedTab);
3373
3399
  } catch {
3374
3400
  setOpen(defaultOpen);
3401
+ setPinned(keepOpen);
3375
3402
  }
3376
3403
  const unwatch = watchNavigation(onNavigate);
3377
3404
  return () => {
3378
3405
  clearTimeout(timer);
3379
3406
  unwatch();
3380
3407
  };
3381
- }, [prefix, defaultOpen]);
3408
+ }, [prefix, defaultOpen, keepOpen]);
3382
3409
  const toggle = react.useCallback((next, focusLauncher = false) => {
3383
3410
  setOpen(next);
3384
3411
  focusOnOpen.current = next;
3385
3412
  if (focusLauncher) launcher.current?.focus();
3386
3413
  remember(OPEN_KEY, next ? "1" : "0");
3387
3414
  }, []);
3415
+ const pin = (next) => {
3416
+ setPinned(next);
3417
+ remember(PIN_KEY, next ? "1" : "0");
3418
+ };
3388
3419
  react.useEffect(() => {
3389
3420
  if (!open) return;
3390
3421
  if (focusOnOpen.current) card.current?.focus();
3422
+ if (pinned) return;
3391
3423
  const onKey = (e) => {
3392
3424
  if (e.key === "Escape" && root.current?.contains(document.activeElement)) toggle(false, true);
3393
3425
  };
3394
3426
  const onDown = (e) => {
3395
- if (root.current && !root.current.contains(e.target)) toggle(false);
3427
+ if (root.current && !root.current.contains(e.target)) setOpen(false);
3396
3428
  };
3397
3429
  document.addEventListener("keydown", onKey);
3398
3430
  document.addEventListener("mousedown", onDown);
@@ -3400,7 +3432,7 @@ function XeniaDebugPanel({ prefix = DEFAULT_PREFIX, position = "bottom-right", d
3400
3432
  document.removeEventListener("keydown", onKey);
3401
3433
  document.removeEventListener("mousedown", onDown);
3402
3434
  };
3403
- }, [open, toggle]);
3435
+ }, [open, pinned, toggle]);
3404
3436
  if (!entry) return null;
3405
3437
  const status = debugStatus(entry);
3406
3438
  const v = view(entry);
@@ -3445,7 +3477,28 @@ function XeniaDebugPanel({ prefix = DEFAULT_PREFIX, position = "bottom-right", d
3445
3477
  typeof v.ms === "number" && v.source === "xenia" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "xdp-ms", children: [
3446
3478
  v.ms,
3447
3479
  " ms"
3448
- ] }) : null
3480
+ ] }) : null,
3481
+ /* @__PURE__ */ jsxRuntime.jsx(
3482
+ "button",
3483
+ {
3484
+ type: "button",
3485
+ className: "xdp-pin",
3486
+ "aria-pressed": pinned,
3487
+ "aria-label": "Keep open",
3488
+ title: pinned ? "Pinned: only the Xenia button closes this" : "Keep open: clicks elsewhere won't close it",
3489
+ onClick: () => pin(!pinned),
3490
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsxRuntime.jsx(
3491
+ "path",
3492
+ {
3493
+ d: "M15 3l6 6-3 1-4 4 1 5-2 2-4-4-5 5-1-1 5-5-4-4 2-2 5 1 4-4z",
3494
+ fill: pinned ? "currentColor" : "none",
3495
+ stroke: "currentColor",
3496
+ strokeWidth: "1.8",
3497
+ strokeLinejoin: "round"
3498
+ }
3499
+ ) })
3500
+ }
3501
+ )
3449
3502
  ] }),
3450
3503
  /* @__PURE__ */ jsxRuntime.jsx("code", { className: "xdp-path", title: v.page, children: v.page }),
3451
3504
  status === "attention" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "xdp-alert", children: v.source === "timeout" ? "Xenia didn't answer within the time budget." : "The decision failed; the proxy's onError has the cause." }) : null
@@ -3614,6 +3667,11 @@ var STYLES2 = `
3614
3667
  code.xdp-chip{font-size:11.5px}
3615
3668
  .xdp-chip[data-tone=holdout]{background:var(--xdp-warn-tint);color:var(--xdp-warn);font-weight:600}
3616
3669
  .xdp-ms{margin-left:auto;color:var(--xdp-faint)}
3670
+ .xdp-pin{margin-left:auto;width:26px;height:26px;display:grid;place-items:center;border:0;border-radius:7px;background:transparent;color:var(--xdp-faint);cursor:pointer}
3671
+ .xdp-ms + .xdp-pin{margin-left:4px}
3672
+ .xdp-pin:hover{background:var(--xdp-soft);color:var(--xdp-muted)}
3673
+ .xdp-pin[aria-pressed=true]{color:var(--xdp-blue);background:var(--xdp-soft)}
3674
+ .xdp-pin:focus-visible{outline:2px solid var(--xdp-blue);outline-offset:1px}
3617
3675
  .xdp-path{display:block;margin-top:8px;font-size:13px;color:var(--xdp-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
3618
3676
  .xdp-alert{margin:8px 0 0;padding:8px 10px;border-radius:8px;background:var(--xdp-warn-tint);color:var(--xdp-warn)}
3619
3677
  .xdp-tabs{display:flex;gap:4px;padding:0 12px;border-bottom:1px solid var(--xdp-border)}