@gfed-medusa/sf-lib-common 3.7.4 → 3.8.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.
Files changed (120) hide show
  1. package/dist/components/breadcrumbs/index.d.ts +2 -2
  2. package/dist/components/cart-mismatch-banner/index.d.ts +2 -2
  3. package/dist/components/delete-button/index.d.ts +2 -2
  4. package/dist/components/device-id-setter/index.d.ts +5 -0
  5. package/dist/components/device-id-setter/index.d.ts.map +1 -0
  6. package/dist/components/device-id-setter/index.js +16 -0
  7. package/dist/components/device-id-setter/index.js.map +1 -0
  8. package/dist/components/error-message/index.d.ts +2 -2
  9. package/dist/components/error-message/index.d.ts.map +1 -1
  10. package/dist/components/free-shipping-price-nudge/index.d.ts +2 -2
  11. package/dist/components/free-shipping-price-nudge/index.d.ts.map +1 -1
  12. package/dist/components/interactive-link/index.d.ts +2 -2
  13. package/dist/components/interactive-link/index.d.ts.map +1 -1
  14. package/dist/components/line-item-options/index.d.ts +2 -2
  15. package/dist/components/line-item-options/index.d.ts.map +1 -1
  16. package/dist/components/localized-client-link/index.d.ts +2 -2
  17. package/dist/components/modal/index.d.ts +2 -2
  18. package/dist/components/modal/index.d.ts.map +1 -1
  19. package/dist/components/personalized-content/components/hero-banner.d.ts +31 -0
  20. package/dist/components/personalized-content/components/hero-banner.d.ts.map +1 -0
  21. package/dist/components/personalized-content/components/hero-banner.js +85 -0
  22. package/dist/components/personalized-content/components/hero-banner.js.map +1 -0
  23. package/dist/components/personalized-content/components/index.d.ts +2 -0
  24. package/dist/components/personalized-content/components/index.js +3 -0
  25. package/dist/components/preview-price/index.d.ts +2 -2
  26. package/dist/components/product-card/index.d.ts +2 -2
  27. package/dist/components/product-preview/index.d.ts +2 -4
  28. package/dist/components/product-preview/index.d.ts.map +1 -1
  29. package/dist/components/product-preview/index.js +1 -2
  30. package/dist/components/product-preview/index.js.map +1 -1
  31. package/dist/components/submit-button/index.d.ts +2 -2
  32. package/dist/components/thumbnail/index.d.ts +0 -1
  33. package/dist/components/thumbnail/index.d.ts.map +1 -1
  34. package/dist/components/thumbnail/index.js +9 -11
  35. package/dist/components/thumbnail/index.js.map +1 -1
  36. package/dist/lib/context/apollo-context.d.ts +2 -2
  37. package/dist/lib/context/modal-context.d.ts +2 -2
  38. package/dist/lib/context/modal-context.d.ts.map +1 -1
  39. package/dist/lib/data/context.d.ts +2 -2
  40. package/dist/lib/data/context.d.ts.map +1 -1
  41. package/dist/lib/data/personalization.d.ts +51 -0
  42. package/dist/lib/data/personalization.d.ts.map +1 -0
  43. package/dist/lib/data/personalization.js +77 -0
  44. package/dist/lib/data/personalization.js.map +1 -0
  45. package/dist/lib/gql/apollo-client.d.ts.map +1 -1
  46. package/dist/lib/gql/apollo-client.js +6 -2
  47. package/dist/lib/gql/apollo-client.js.map +1 -1
  48. package/dist/lib/gql/fragments/cart.d.ts +9 -9
  49. package/dist/lib/gql/fragments/customer.d.ts +3 -3
  50. package/dist/lib/gql/fragments/product.d.ts +8 -8
  51. package/dist/lib/gql/mutations/cart.d.ts +6 -6
  52. package/dist/lib/gql/queries/cart-summary.d.ts +2 -2
  53. package/dist/lib/gql/queries/cart-summary.js +1 -1
  54. package/dist/lib/gql/queries/cart-summary.js.map +1 -1
  55. package/dist/lib/gql/queries/cart-total.d.ts +7 -0
  56. package/dist/lib/gql/queries/cart-total.d.ts.map +1 -0
  57. package/dist/lib/gql/queries/cart-total.js +14 -0
  58. package/dist/lib/gql/queries/cart-total.js.map +1 -0
  59. package/dist/lib/gql/queries/cart.d.ts +2 -2
  60. package/dist/lib/gql/queries/cart.js +1 -1
  61. package/dist/lib/gql/queries/cart.js.map +1 -1
  62. package/dist/lib/gql/queries/collections.d.ts +3 -3
  63. package/dist/lib/gql/queries/customer.d.ts +2 -2
  64. package/dist/lib/gql/queries/footer.d.ts +3 -3
  65. package/dist/lib/gql/queries/home-banner.d.ts +2 -2
  66. package/dist/lib/gql/queries/order.d.ts +4 -4
  67. package/dist/lib/gql/queries/order.d.ts.map +1 -1
  68. package/dist/lib/gql/queries/order.js +5 -0
  69. package/dist/lib/gql/queries/order.js.map +1 -1
  70. package/dist/lib/gql/queries/product-personalization.d.ts +7 -0
  71. package/dist/lib/gql/queries/product-personalization.d.ts.map +1 -0
  72. package/dist/lib/gql/queries/product-personalization.js +22 -0
  73. package/dist/lib/gql/queries/product-personalization.js.map +1 -0
  74. package/dist/lib/gql/queries/product.d.ts +2 -2
  75. package/dist/lib/gql/queries/regions.d.ts +3 -3
  76. package/dist/lib/hooks/use-apollo.d.ts +2 -2
  77. package/dist/lib/hooks/use-time-on-page.d.ts +13 -0
  78. package/dist/lib/hooks/use-time-on-page.d.ts.map +1 -0
  79. package/dist/lib/hooks/use-time-on-page.js +46 -0
  80. package/dist/lib/hooks/use-time-on-page.js.map +1 -0
  81. package/dist/lib/personalization/behavior-tracker.d.ts +1 -5
  82. package/dist/lib/personalization/behavior-tracker.d.ts.map +1 -1
  83. package/dist/lib/personalization/behavior-tracker.js +1 -18
  84. package/dist/lib/personalization/behavior-tracker.js.map +1 -1
  85. package/dist/lib/personalization/client-signal.d.ts +26 -0
  86. package/dist/lib/personalization/client-signal.d.ts.map +1 -0
  87. package/dist/lib/personalization/client-signal.js +105 -0
  88. package/dist/lib/personalization/client-signal.js.map +1 -0
  89. package/dist/lib/personalization/config.d.ts +2 -6
  90. package/dist/lib/personalization/config.d.ts.map +1 -1
  91. package/dist/lib/personalization/config.js +2 -16
  92. package/dist/lib/personalization/config.js.map +1 -1
  93. package/dist/lib/personalization/device-id.d.ts +5 -0
  94. package/dist/lib/personalization/device-id.d.ts.map +1 -0
  95. package/dist/lib/personalization/device-id.js +24 -0
  96. package/dist/lib/personalization/device-id.js.map +1 -0
  97. package/dist/lib/personalization/personalization-gql.d.ts +9 -0
  98. package/dist/lib/personalization/personalization-gql.d.ts.map +1 -0
  99. package/dist/lib/personalization/personalization-gql.js +42 -0
  100. package/dist/lib/personalization/personalization-gql.js.map +1 -0
  101. package/dist/lib/utils/imagekit.d.ts +2 -2
  102. package/dist/lib/utils/imagekit.js +1 -1
  103. package/dist/lib/utils/imagekit.js.map +1 -1
  104. package/dist/types/graphql.d.ts +247 -5
  105. package/dist/types/graphql.d.ts.map +1 -1
  106. package/dist/types/graphql.js +410 -3
  107. package/dist/types/graphql.js.map +1 -1
  108. package/package.json +1 -1
  109. package/dist/lib/data/contextual-banner.d.ts +0 -15
  110. package/dist/lib/data/contextual-banner.d.ts.map +0 -1
  111. package/dist/lib/data/contextual-banner.js +0 -19
  112. package/dist/lib/data/contextual-banner.js.map +0 -1
  113. package/dist/lib/gql/queries/contextual-banner.d.ts +0 -7
  114. package/dist/lib/gql/queries/contextual-banner.d.ts.map +0 -1
  115. package/dist/lib/gql/queries/contextual-banner.js +0 -21
  116. package/dist/lib/gql/queries/contextual-banner.js.map +0 -1
  117. package/dist/lib/personalization/user-profile.d.ts +0 -15
  118. package/dist/lib/personalization/user-profile.d.ts.map +0 -1
  119. package/dist/lib/personalization/user-profile.js +0 -47
  120. package/dist/lib/personalization/user-profile.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"behavior-tracker.d.ts","names":[],"sources":["../../../src/lib/personalization/behavior-tracker.ts"],"sourcesContent":[],"mappings":";UAEiB,WAAA;EAAA,QAAA,CAAA,EAAA,MAAW;EAgBZ,OAAA,CAAA,EAAA,MAAA,EAAA;EAUA,OAAA,CAAA,EAvBJ,MAuBI,CAAA,MAAgB,EAAA,OAAO,CAAA;AAIvC;AASgB,iBAvBA,gBAAA,CAAA,CAuBS,EAvBW,WAuBX;AAKT,iBAlBA,gBAAA,CAkBuB,IAAA,EAlBA,WAkBA,CAAA,EAAA,IAAA;AAKvB,iBAnBA,UAAA,CAmBY,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,CAAA,EAAA,IAAA;iBAVZ,SAAA;iBAKA,aAAA,CAAA,GAAiB;iBAKjB,YAAA,CAAA"}
1
+ {"version":3,"file":"behavior-tracker.d.ts","names":[],"sources":["../../../src/lib/personalization/behavior-tracker.ts"],"sourcesContent":[],"mappings":";UAEiB,WAAA;EAAA,QAAA,CAAA,EAAA,MAAW;EAgBZ,OAAA,CAAA,EAAA,MAAA,EAAA;EAUA,OAAA,CAAA,EAvBJ,MAuBI,CAAA,MAAgB,EAAA,OAAO,CAAA;;iBAVvB,gBAAA,CAAA,GAAoB;iBAUpB,gBAAA,OAAuB"}
@@ -15,24 +15,7 @@ function getSegmentCookie() {
15
15
  function setSegmentCookie(data) {
16
16
  document.cookie = `${SIGNAL_COOKIE}=${encodeURIComponent(JSON.stringify(data))};${buildCookieAttrs()}`;
17
17
  }
18
- function emitSignal(type, payload) {
19
- const data = getSegmentCookie();
20
- if (!data.signals) data.signals = {};
21
- data.signals[type] = payload ?? true;
22
- setSegmentCookie(data);
23
- }
24
- function getSignal(type) {
25
- return getSegmentCookie().signals?.[type];
26
- }
27
- function getAllSignals() {
28
- return getSegmentCookie().signals ?? {};
29
- }
30
- function clearSignals() {
31
- const data = getSegmentCookie();
32
- data.signals = {};
33
- setSegmentCookie(data);
34
- }
35
18
 
36
19
  //#endregion
37
- export { clearSignals, emitSignal, getAllSignals, getSegmentCookie, getSignal, setSegmentCookie };
20
+ export { getSegmentCookie, setSegmentCookie };
38
21
  //# sourceMappingURL=behavior-tracker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"behavior-tracker.js","names":[],"sources":["../../../src/lib/personalization/behavior-tracker.ts"],"sourcesContent":["import { PERSONALIZATION_CONFIG } from './config';\n\nexport interface SegmentData {\n interest?: string;\n history?: string[];\n signals?: Record<string, unknown>;\n}\n\nconst SIGNAL_COOKIE = '_jg_segment';\n\nfunction buildCookieAttrs(): string {\n const maxAge = 60 * 60 * 24 * 7;\n if (process.env.NODE_ENV === 'production') {\n return `path=/;max-age=${maxAge};SameSite=none;secure;domain=.justgood.win`;\n }\n return `path=/;max-age=${maxAge};SameSite=Lax`;\n}\n\nexport function getSegmentCookie(): SegmentData {\n const match = document.cookie.match(/_jg_segment=([^;]+)/);\n if (!match || !match[1]) return {};\n try {\n return JSON.parse(decodeURIComponent(match[1]));\n } catch {\n return {};\n }\n}\n\nexport function setSegmentCookie(data: SegmentData) {\n document.cookie = `${SIGNAL_COOKIE}=${encodeURIComponent(JSON.stringify(data))};${buildCookieAttrs()}`;\n}\n\nexport function emitSignal(type: string, payload?: unknown) {\n const data = getSegmentCookie();\n if (!data.signals) {\n data.signals = {};\n }\n data.signals[type] = payload ?? true;\n setSegmentCookie(data);\n}\n\nexport function getSignal(type: string): unknown {\n const data = getSegmentCookie();\n return data.signals?.[type];\n}\n\nexport function getAllSignals(): Record<string, unknown> {\n const data = getSegmentCookie();\n return data.signals ?? {};\n}\n\nexport function clearSignals() {\n const data = getSegmentCookie();\n data.signals = {};\n setSegmentCookie(data);\n}\n"],"mappings":";AAQA,MAAM,gBAAgB;AAEtB,SAAS,mBAA2B;AAGhC,QAAO,kBAFM,OAAU,KAAK,EAEI;;AAKpC,SAAgB,mBAAgC;CAC9C,MAAM,QAAQ,SAAS,OAAO,MAAM,sBAAsB;AAC1D,KAAI,CAAC,SAAS,CAAC,MAAM,GAAI,QAAO,EAAE;AAClC,KAAI;AACF,SAAO,KAAK,MAAM,mBAAmB,MAAM,GAAG,CAAC;SACzC;AACN,SAAO,EAAE;;;AAIb,SAAgB,iBAAiB,MAAmB;AAClD,UAAS,SAAS,GAAG,cAAc,GAAG,mBAAmB,KAAK,UAAU,KAAK,CAAC,CAAC,GAAG,kBAAkB;;AAGtG,SAAgB,WAAW,MAAc,SAAmB;CAC1D,MAAM,OAAO,kBAAkB;AAC/B,KAAI,CAAC,KAAK,QACR,MAAK,UAAU,EAAE;AAEnB,MAAK,QAAQ,QAAQ,WAAW;AAChC,kBAAiB,KAAK;;AAGxB,SAAgB,UAAU,MAAuB;AAE/C,QADa,kBAAkB,CACnB,UAAU;;AAGxB,SAAgB,gBAAyC;AAEvD,QADa,kBAAkB,CACnB,WAAW,EAAE;;AAG3B,SAAgB,eAAe;CAC7B,MAAM,OAAO,kBAAkB;AAC/B,MAAK,UAAU,EAAE;AACjB,kBAAiB,KAAK"}
1
+ {"version":3,"file":"behavior-tracker.js","names":[],"sources":["../../../src/lib/personalization/behavior-tracker.ts"],"sourcesContent":["import { PERSONALIZATION_CONFIG } from './config';\n\nexport interface SegmentData {\n interest?: string;\n history?: string[];\n signals?: Record<string, unknown>;\n}\n\nconst SIGNAL_COOKIE = '_jg_segment';\n\nfunction buildCookieAttrs(): string {\n const maxAge = 60 * 60 * 24 * 7;\n if (process.env.NODE_ENV === 'production') {\n return `path=/;max-age=${maxAge};SameSite=none;secure;domain=.justgood.win`;\n }\n return `path=/;max-age=${maxAge};SameSite=Lax`;\n}\n\nexport function getSegmentCookie(): SegmentData {\n const match = document.cookie.match(/_jg_segment=([^;]+)/);\n if (!match || !match[1]) return {};\n try {\n return JSON.parse(decodeURIComponent(match[1]));\n } catch {\n return {};\n }\n}\n\nexport function setSegmentCookie(data: SegmentData) {\n document.cookie = `${SIGNAL_COOKIE}=${encodeURIComponent(JSON.stringify(data))};${buildCookieAttrs()}`;\n}\n\n\n"],"mappings":";AAQA,MAAM,gBAAgB;AAEtB,SAAS,mBAA2B;AAGhC,QAAO,kBAFM,OAAU,KAAK,EAEI;;AAKpC,SAAgB,mBAAgC;CAC9C,MAAM,QAAQ,SAAS,OAAO,MAAM,sBAAsB;AAC1D,KAAI,CAAC,SAAS,CAAC,MAAM,GAAI,QAAO,EAAE;AAClC,KAAI;AACF,SAAO,KAAK,MAAM,mBAAmB,MAAM,GAAG,CAAC;SACzC;AACN,SAAO,EAAE;;;AAIb,SAAgB,iBAAiB,MAAmB;AAClD,UAAS,SAAS,GAAG,cAAc,GAAG,mBAAmB,KAAK,UAAU,KAAK,CAAC,CAAC,GAAG,kBAAkB"}
@@ -0,0 +1,26 @@
1
+ import { SignalType } from "../../types/graphql.js";
2
+
3
+ //#region src/lib/personalization/client-signal.d.ts
4
+
5
+ /**
6
+ * Resets the cached user ID. Call this after login/logout to ensure
7
+ * subsequent signals carry the correct userId.
8
+ */
9
+ declare function invalidateUserId(): void;
10
+ /**
11
+ * Sends a personalization signal from the browser.
12
+ *
13
+ * Uses the default Apollo client which proxies through the shell's /api/graphql
14
+ * route. The proxy injects the x-bff-api-key header server-side, keeping the
15
+ * shared secret out of client-side code.
16
+ *
17
+ * For server-side signals, use `sendSignal()` from `@gfed-medusa/sf-lib-common/lib/data/personalization`
18
+ * which creates an authenticated client with the API key.
19
+ *
20
+ * If `userId` is not provided, it is automatically resolved by fetching
21
+ * `/api/horz/customer` (cached once per page session).
22
+ */
23
+ declare function sendClientSignal(type: SignalType, payload?: Record<string, unknown>, userId?: string): Promise<boolean>;
24
+ //#endregion
25
+ export { invalidateUserId, sendClientSignal };
26
+ //# sourceMappingURL=client-signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-signal.d.ts","names":[],"sources":["../../../src/lib/personalization/client-signal.ts"],"sourcesContent":[],"mappings":";;;;;;AAsDA;AAmBA;AACQ,iBApBQ,gBAAA,CAAA,CAoBR,EAAA,IAAA;;;;;;;;;;;;;;iBADc,gBAAA,OACd,sBACI,2CAET"}
@@ -0,0 +1,105 @@
1
+ import { graphqlMutation } from "../gql/apollo-client.js";
2
+ import { getDeviceId } from "./device-id.js";
3
+ import { SEND_SIGNAL_MUTATION } from "./personalization-gql.js";
4
+
5
+ //#region src/lib/personalization/client-signal.ts
6
+ const USER_ID_FETCH_TIMEOUT_MS = 3e3;
7
+ let resolvedUserId;
8
+ let userIdPromise = null;
9
+ let userIdChecked = false;
10
+ /**
11
+ * Resolves the current user's ID by fetching /api/horz/customer.
12
+ * Results are cached module-globally so the endpoint is only called once
13
+ * per page session (the cache resets on module reload / page refresh).
14
+ *
15
+ * Uses AbortController with a 3-second timeout so that signals are never
16
+ * blocked if the endpoint is unresponsive.
17
+ */
18
+ async function resolveUserId() {
19
+ if (userIdChecked) return resolvedUserId;
20
+ if (userIdPromise) return userIdPromise;
21
+ userIdPromise = (async () => {
22
+ const controller = new AbortController();
23
+ const timeoutId = setTimeout(() => controller.abort(), USER_ID_FETCH_TIMEOUT_MS);
24
+ try {
25
+ const res = await fetch("/api/horz/customer", {
26
+ credentials: "include",
27
+ signal: controller.signal
28
+ });
29
+ if (res.ok) resolvedUserId = (await res.json())?.customer?.id ?? void 0;
30
+ } catch {} finally {
31
+ clearTimeout(timeoutId);
32
+ }
33
+ userIdChecked = true;
34
+ userIdPromise = null;
35
+ return resolvedUserId;
36
+ })();
37
+ return userIdPromise;
38
+ }
39
+ /**
40
+ * Resets the cached user ID. Call this after login/logout to ensure
41
+ * subsequent signals carry the correct userId.
42
+ */
43
+ function invalidateUserId() {
44
+ resolvedUserId = void 0;
45
+ userIdPromise = null;
46
+ userIdChecked = false;
47
+ }
48
+ /**
49
+ * Sends a personalization signal from the browser.
50
+ *
51
+ * Uses the default Apollo client which proxies through the shell's /api/graphql
52
+ * route. The proxy injects the x-bff-api-key header server-side, keeping the
53
+ * shared secret out of client-side code.
54
+ *
55
+ * For server-side signals, use `sendSignal()` from `@gfed-medusa/sf-lib-common/lib/data/personalization`
56
+ * which creates an authenticated client with the API key.
57
+ *
58
+ * If `userId` is not provided, it is automatically resolved by fetching
59
+ * `/api/horz/customer` (cached once per page session).
60
+ */
61
+ async function sendClientSignal(type, payload, userId) {
62
+ const deviceId = getDeviceId();
63
+ if (!deviceId) return false;
64
+ if (!userId) userId = await resolveUserId();
65
+ const input = {
66
+ deviceId,
67
+ type,
68
+ payload,
69
+ url: typeof window !== "undefined" ? window.location.href : void 0,
70
+ timestamp: Date.now()
71
+ };
72
+ if (userId) input.userId = userId;
73
+ try {
74
+ await graphqlMutation({
75
+ mutation: SEND_SIGNAL_MUTATION,
76
+ variables: { input }
77
+ });
78
+ return true;
79
+ } catch (apolloError) {
80
+ console.warn("[sendClientSignal] Apollo mutation failed, trying fetch fallback:", type, apolloError);
81
+ }
82
+ try {
83
+ const res = await fetch("/api/graphql", {
84
+ method: "POST",
85
+ headers: { "Content-Type": "application/json" },
86
+ credentials: "include",
87
+ body: JSON.stringify({
88
+ query: `mutation SendSignal($input: SignalInput!) { sendSignal(input: $input) { success } }`,
89
+ variables: { input }
90
+ })
91
+ });
92
+ if (!res.ok) {
93
+ console.warn("[sendClientSignal] Fetch fallback failed:", type, res.status, res.statusText);
94
+ return false;
95
+ }
96
+ return true;
97
+ } catch (fetchError) {
98
+ console.warn("[sendClientSignal] Fetch fallback also failed:", type, fetchError);
99
+ return false;
100
+ }
101
+ }
102
+
103
+ //#endregion
104
+ export { invalidateUserId, sendClientSignal };
105
+ //# sourceMappingURL=client-signal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-signal.js","names":["resolvedUserId: string | undefined","userIdPromise: Promise<string | undefined> | null","input: SignalInput"],"sources":["../../../src/lib/personalization/client-signal.ts"],"sourcesContent":["import { graphqlMutation } from '@/lib/gql/apollo-client';\nimport { SEND_SIGNAL_MUTATION } from '@/lib/personalization/personalization-gql';\nimport { getDeviceId } from '@/lib/personalization/device-id';\nimport type { SignalInput, SignalType } from '@/types/graphql';\n\nconst USER_ID_FETCH_TIMEOUT_MS = 3_000;\n\n// Module-level cache for the resolved customer ID\n// userIdChecked tracks whether we've attempted resolution\nlet resolvedUserId: string | undefined;\nlet userIdPromise: Promise<string | undefined> | null = null;\nlet userIdChecked = false;\n\n/**\n * Resolves the current user's ID by fetching /api/horz/customer.\n * Results are cached module-globally so the endpoint is only called once\n * per page session (the cache resets on module reload / page refresh).\n *\n * Uses AbortController with a 3-second timeout so that signals are never\n * blocked if the endpoint is unresponsive.\n */\nasync function resolveUserId(): Promise<string | undefined> {\n if (userIdChecked) return resolvedUserId;\n if (userIdPromise) return userIdPromise;\n\n userIdPromise = (async () => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), USER_ID_FETCH_TIMEOUT_MS);\n try {\n const res = await fetch('/api/horz/customer', {\n credentials: 'include',\n signal: controller.signal,\n });\n if (res.ok) {\n const data = await res.json();\n resolvedUserId = data?.customer?.id ?? undefined;\n }\n } catch {\n // Network error or timeout — resolvedUserId stays undefined\n } finally {\n clearTimeout(timeoutId);\n }\n userIdChecked = true;\n userIdPromise = null;\n return resolvedUserId;\n })();\n\n return userIdPromise;\n}\n\n/**\n * Resets the cached user ID. Call this after login/logout to ensure\n * subsequent signals carry the correct userId.\n */\nexport function invalidateUserId(): void {\n resolvedUserId = undefined;\n userIdPromise = null;\n userIdChecked = false;\n}\n\n/**\n * Sends a personalization signal from the browser.\n *\n * Uses the default Apollo client which proxies through the shell's /api/graphql\n * route. The proxy injects the x-bff-api-key header server-side, keeping the\n * shared secret out of client-side code.\n *\n * For server-side signals, use `sendSignal()` from `@gfed-medusa/sf-lib-common/lib/data/personalization`\n * which creates an authenticated client with the API key.\n *\n * If `userId` is not provided, it is automatically resolved by fetching\n * `/api/horz/customer` (cached once per page session).\n */\nexport async function sendClientSignal(\n type: SignalType,\n payload?: Record<string, unknown>,\n userId?: string\n): Promise<boolean> {\n const deviceId = getDeviceId();\n if (!deviceId) return false;\n\n // Auto-resolve userId if not explicitly provided\n if (!userId) {\n userId = await resolveUserId();\n }\n\n const input: SignalInput = {\n deviceId,\n type,\n payload,\n url: typeof window !== 'undefined' ? window.location.href : undefined,\n timestamp: Date.now(),\n };\n\n if (userId) {\n input.userId = userId;\n }\n\n // Try Apollo client mutation first\n try {\n await graphqlMutation({\n mutation: SEND_SIGNAL_MUTATION,\n variables: { input },\n });\n return true;\n } catch (apolloError) {\n console.warn(\n '[sendClientSignal] Apollo mutation failed, trying fetch fallback:',\n type,\n apolloError\n );\n }\n\n // Fallback: direct fetch to /api/graphql\n try {\n const res = await fetch('/api/graphql', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({\n query: `mutation SendSignal($input: SignalInput!) { sendSignal(input: $input) { success } }`,\n variables: { input },\n }),\n });\n if (!res.ok) {\n console.warn(\n '[sendClientSignal] Fetch fallback failed:',\n type,\n res.status,\n res.statusText\n );\n return false;\n }\n return true;\n } catch (fetchError) {\n console.warn('[sendClientSignal] Fetch fallback also failed:', type, fetchError);\n return false;\n }\n}\n"],"mappings":";;;;;AAKA,MAAM,2BAA2B;AAIjC,IAAIA;AACJ,IAAIC,gBAAoD;AACxD,IAAI,gBAAgB;;;;;;;;;AAUpB,eAAe,gBAA6C;AAC1D,KAAI,cAAe,QAAO;AAC1B,KAAI,cAAe,QAAO;AAE1B,kBAAiB,YAAY;EAC3B,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,YAAY,iBAAiB,WAAW,OAAO,EAAE,yBAAyB;AAChF,MAAI;GACF,MAAM,MAAM,MAAM,MAAM,sBAAsB;IAC5C,aAAa;IACb,QAAQ,WAAW;IACpB,CAAC;AACF,OAAI,IAAI,GAEN,mBADa,MAAM,IAAI,MAAM,GACN,UAAU,MAAM;UAEnC,WAEE;AACR,gBAAa,UAAU;;AAEzB,kBAAgB;AAChB,kBAAgB;AAChB,SAAO;KACL;AAEJ,QAAO;;;;;;AAOT,SAAgB,mBAAyB;AACvC,kBAAiB;AACjB,iBAAgB;AAChB,iBAAgB;;;;;;;;;;;;;;;AAgBlB,eAAsB,iBACpB,MACA,SACA,QACkB;CAClB,MAAM,WAAW,aAAa;AAC9B,KAAI,CAAC,SAAU,QAAO;AAGtB,KAAI,CAAC,OACH,UAAS,MAAM,eAAe;CAGhC,MAAMC,QAAqB;EACzB;EACA;EACA;EACA,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;EAC5D,WAAW,KAAK,KAAK;EACtB;AAED,KAAI,OACF,OAAM,SAAS;AAIjB,KAAI;AACF,QAAM,gBAAgB;GACpB,UAAU;GACV,WAAW,EAAE,OAAO;GACrB,CAAC;AACF,SAAO;UACA,aAAa;AACpB,UAAQ,KACN,qEACA,MACA,YACD;;AAIH,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,gBAAgB;GACtC,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,aAAa;GACb,MAAM,KAAK,UAAU;IACnB,OAAO;IACP,WAAW,EAAE,OAAO;IACrB,CAAC;GACH,CAAC;AACF,MAAI,CAAC,IAAI,IAAI;AACX,WAAQ,KACN,6CACA,MACA,IAAI,QACJ,IAAI,WACL;AACD,UAAO;;AAET,SAAO;UACA,YAAY;AACnB,UAAQ,KAAK,kDAAkD,MAAM,WAAW;AAChF,SAAO"}
@@ -16,16 +16,12 @@ interface PersonalizationConfig {
16
16
  dismissCooldownMs: number;
17
17
  bannerAutoDismissMs: number;
18
18
  historyMaxLength: number;
19
- priceThresholdUsd: number;
19
+ priceThreshold: number;
20
20
  pdpHesitationMs: number;
21
21
  highScrollThreshold: number;
22
22
  }
23
23
  declare const PERSONALIZATION_CONFIG: PersonalizationConfig;
24
- declare function getSegmentIdFromCategory(categoryHandle: string): string | null;
25
24
  declare function getSegmentIdFromCollection(collectionHandle: string | undefined): string | null;
26
- declare function getAllSegmentIds(): string[];
27
- declare function getSignalDefinition(signalId: string): SignalDefinition | undefined;
28
- declare function getAllSignalIds(): string[];
29
25
  //#endregion
30
- export { PERSONALIZATION_CONFIG, PersonalizationConfig, SegmentDefinition, SignalDefinition, getAllSegmentIds, getAllSignalIds, getSegmentIdFromCategory, getSegmentIdFromCollection, getSignalDefinition };
26
+ export { PERSONALIZATION_CONFIG, PersonalizationConfig, SegmentDefinition, SignalDefinition, getSegmentIdFromCollection };
31
27
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/lib/personalization/config.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,EAAA,EAAA,MAAA;EAOA,KAAA,EAAA,MAAA;EAMA,eAAA,EAAA,MAAA,EAAqB;EAWzB,iBAAA,EAAA,MAiCZ,EAAA;AAED;AAUgB,UA9DC,gBAAA,CA8DyB;EAW1B,EAAA,EAAA,MAAA;EAIA,WAAA,EAAA,MAAA;EAIA,aAAA,EAAA,MAAe;;UA3Ed,qBAAA;YACL;WACD;;;;;;;;cASE,wBAAwB;iBAmCrB,wBAAA;iBAUA,0BAAA;iBAWA,gBAAA,CAAA;iBAIA,mBAAA,oBAAuC;iBAIvC,eAAA,CAAA"}
1
+ {"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/lib/personalization/config.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,EAAA,EAAA,MAAA;EAOA,KAAA,EAAA,MAAA;EAMA,eAAA,EAAA,MAAA,EAAqB;EAWzB,iBAAA,EAAA,MAiCZ,EAAA;AAED;UApDiB,gBAAA;;;;;UAMA,qBAAA;YACL;WACD;;;;;;;;cASE,wBAAwB;iBAmCrB,0BAAA"}
@@ -47,31 +47,17 @@ const PERSONALIZATION_CONFIG = {
47
47
  dismissCooldownMs: 3600 * 1e3,
48
48
  bannerAutoDismissMs: 3e4,
49
49
  historyMaxLength: 20,
50
- priceThresholdUsd: 200,
50
+ priceThreshold: 80,
51
51
  pdpHesitationMs: 3e4,
52
52
  highScrollThreshold: .8
53
53
  };
54
- function getSegmentIdFromCategory(categoryHandle) {
55
- const normalized = categoryHandle.toLowerCase().replace(/[-_\s]/g, "");
56
- for (const segment of PERSONALIZATION_CONFIG.segments) if (segment.categoryHandles.includes(normalized)) return segment.id;
57
- return null;
58
- }
59
54
  function getSegmentIdFromCollection(collectionHandle) {
60
55
  if (!collectionHandle) return null;
61
56
  const normalized = collectionHandle.toLowerCase().replace(/[-_\s]/g, "");
62
57
  for (const segment of PERSONALIZATION_CONFIG.segments) if (segment.collectionHandles.includes(normalized)) return segment.id;
63
58
  return null;
64
59
  }
65
- function getAllSegmentIds() {
66
- return PERSONALIZATION_CONFIG.segments.map((s) => s.id);
67
- }
68
- function getSignalDefinition(signalId) {
69
- return PERSONALIZATION_CONFIG.signals.find((s) => s.id === signalId);
70
- }
71
- function getAllSignalIds() {
72
- return PERSONALIZATION_CONFIG.signals.map((s) => s.id);
73
- }
74
60
 
75
61
  //#endregion
76
- export { PERSONALIZATION_CONFIG, getAllSegmentIds, getAllSignalIds, getSegmentIdFromCategory, getSegmentIdFromCollection, getSignalDefinition };
62
+ export { PERSONALIZATION_CONFIG, getSegmentIdFromCollection };
77
63
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":["PERSONALIZATION_CONFIG: PersonalizationConfig"],"sources":["../../../src/lib/personalization/config.ts"],"sourcesContent":["export interface SegmentDefinition {\n id: string;\n label: string;\n categoryHandles: string[];\n collectionHandles: string[];\n}\n\nexport interface SignalDefinition {\n id: string;\n description: string;\n bannerTrigger: string;\n}\n\nexport interface PersonalizationConfig {\n segments: SegmentDefinition[];\n signals: SignalDefinition[];\n dismissCooldownMs: number;\n bannerAutoDismissMs: number;\n historyMaxLength: number;\n priceThresholdUsd: number;\n pdpHesitationMs: number;\n highScrollThreshold: number;\n}\n\nexport const PERSONALIZATION_CONFIG: PersonalizationConfig = {\n segments: [\n {\n id: 'mens',\n label: \"Men's\",\n categoryHandles: ['mens', 'men', 'mens-collection', 'menswear', 'menstwo'],\n collectionHandles: ['mens', 'men', 'mens-collection', 'menswear', 'menstwo'],\n },\n {\n id: 'womens',\n label: \"Women's\",\n categoryHandles: ['womens', 'women', 'womens-collection', 'womenswear', 'womenstwo'],\n collectionHandles: ['womens', 'women', 'womens-collection', 'womenswear', 'womenstwo'],\n },\n ],\n signals: [\n {\n id: 'pdp-hesitation',\n description: 'User on PDP > 30s with expensive product',\n bannerTrigger: 'pdp-hesitation',\n },\n {\n id: 'high-scroll-no-action',\n description: 'User scrolled 80% without adding to cart',\n bannerTrigger: 'high-scroll-no-action',\n },\n ],\n dismissCooldownMs: 60 * 60 * 1000,\n bannerAutoDismissMs: 30_000,\n historyMaxLength: 20,\n priceThresholdUsd: 200,\n pdpHesitationMs: 30_000,\n highScrollThreshold: 0.8,\n};\n\nexport function getSegmentIdFromCategory(categoryHandle: string): string | null {\n const normalized = categoryHandle.toLowerCase().replace(/[-_\\s]/g, '');\n for (const segment of PERSONALIZATION_CONFIG.segments) {\n if (segment.categoryHandles.includes(normalized)) {\n return segment.id;\n }\n }\n return null;\n}\n\nexport function getSegmentIdFromCollection(collectionHandle: string | undefined): string | null {\n if (!collectionHandle) return null;\n const normalized = collectionHandle.toLowerCase().replace(/[-_\\s]/g, '');\n for (const segment of PERSONALIZATION_CONFIG.segments) {\n if (segment.collectionHandles.includes(normalized)) {\n return segment.id;\n }\n }\n return null;\n}\n\nexport function getAllSegmentIds(): string[] {\n return PERSONALIZATION_CONFIG.segments.map((s) => s.id);\n}\n\nexport function getSignalDefinition(signalId: string): SignalDefinition | undefined {\n return PERSONALIZATION_CONFIG.signals.find((s) => s.id === signalId);\n}\n\nexport function getAllSignalIds(): string[] {\n return PERSONALIZATION_CONFIG.signals.map((s) => s.id);\n}"],"mappings":";AAwBA,MAAaA,yBAAgD;CAC3D,UAAU,CACR;EACE,IAAI;EACJ,OAAO;EACP,iBAAiB;GAAC;GAAQ;GAAO;GAAmB;GAAY;GAAU;EAC1E,mBAAmB;GAAC;GAAQ;GAAO;GAAmB;GAAY;GAAU;EAC7E,EACD;EACE,IAAI;EACJ,OAAO;EACP,iBAAiB;GAAC;GAAU;GAAS;GAAqB;GAAc;GAAY;EACpF,mBAAmB;GAAC;GAAU;GAAS;GAAqB;GAAc;GAAY;EACvF,CACF;CACD,SAAS,CACP;EACE,IAAI;EACJ,aAAa;EACb,eAAe;EAChB,EACD;EACE,IAAI;EACJ,aAAa;EACb,eAAe;EAChB,CACF;CACD,mBAAmB,OAAU;CAC7B,qBAAqB;CACrB,kBAAkB;CAClB,mBAAmB;CACnB,iBAAiB;CACjB,qBAAqB;CACtB;AAED,SAAgB,yBAAyB,gBAAuC;CAC9E,MAAM,aAAa,eAAe,aAAa,CAAC,QAAQ,WAAW,GAAG;AACtE,MAAK,MAAM,WAAW,uBAAuB,SAC3C,KAAI,QAAQ,gBAAgB,SAAS,WAAW,CAC9C,QAAO,QAAQ;AAGnB,QAAO;;AAGT,SAAgB,2BAA2B,kBAAqD;AAC9F,KAAI,CAAC,iBAAkB,QAAO;CAC9B,MAAM,aAAa,iBAAiB,aAAa,CAAC,QAAQ,WAAW,GAAG;AACxE,MAAK,MAAM,WAAW,uBAAuB,SAC3C,KAAI,QAAQ,kBAAkB,SAAS,WAAW,CAChD,QAAO,QAAQ;AAGnB,QAAO;;AAGT,SAAgB,mBAA6B;AAC3C,QAAO,uBAAuB,SAAS,KAAK,MAAM,EAAE,GAAG;;AAGzD,SAAgB,oBAAoB,UAAgD;AAClF,QAAO,uBAAuB,QAAQ,MAAM,MAAM,EAAE,OAAO,SAAS;;AAGtE,SAAgB,kBAA4B;AAC1C,QAAO,uBAAuB,QAAQ,KAAK,MAAM,EAAE,GAAG"}
1
+ {"version":3,"file":"config.js","names":["PERSONALIZATION_CONFIG: PersonalizationConfig"],"sources":["../../../src/lib/personalization/config.ts"],"sourcesContent":["export interface SegmentDefinition {\n id: string;\n label: string;\n categoryHandles: string[];\n collectionHandles: string[];\n}\n\nexport interface SignalDefinition {\n id: string;\n description: string;\n bannerTrigger: string;\n}\n\nexport interface PersonalizationConfig {\n segments: SegmentDefinition[];\n signals: SignalDefinition[];\n dismissCooldownMs: number;\n bannerAutoDismissMs: number;\n historyMaxLength: number;\n priceThreshold: number;\n pdpHesitationMs: number;\n highScrollThreshold: number;\n}\n\nexport const PERSONALIZATION_CONFIG: PersonalizationConfig = {\n segments: [\n {\n id: 'mens',\n label: \"Men's\",\n categoryHandles: ['mens', 'men', 'mens-collection', 'menswear', 'menstwo'],\n collectionHandles: ['mens', 'men', 'mens-collection', 'menswear', 'menstwo'],\n },\n {\n id: 'womens',\n label: \"Women's\",\n categoryHandles: ['womens', 'women', 'womens-collection', 'womenswear', 'womenstwo'],\n collectionHandles: ['womens', 'women', 'womens-collection', 'womenswear', 'womenstwo'],\n },\n ],\n signals: [\n {\n id: 'pdp-hesitation',\n description: 'User on PDP > 30s with expensive product',\n bannerTrigger: 'pdp-hesitation',\n },\n {\n id: 'high-scroll-no-action',\n description: 'User scrolled 80% without adding to cart',\n bannerTrigger: 'high-scroll-no-action',\n },\n ],\n dismissCooldownMs: 60 * 60 * 1000,\n bannerAutoDismissMs: 30_000,\n historyMaxLength: 20,\n priceThreshold: 80,\n pdpHesitationMs: 30_000,\n highScrollThreshold: 0.8,\n};\n\nexport function getSegmentIdFromCollection(collectionHandle: string | undefined): string | null {\n if (!collectionHandle) return null;\n const normalized = collectionHandle.toLowerCase().replace(/[-_\\s]/g, '');\n for (const segment of PERSONALIZATION_CONFIG.segments) {\n if (segment.collectionHandles.includes(normalized)) {\n return segment.id;\n }\n }\n return null;\n}\n\n"],"mappings":";AAwBA,MAAaA,yBAAgD;CAC3D,UAAU,CACR;EACE,IAAI;EACJ,OAAO;EACP,iBAAiB;GAAC;GAAQ;GAAO;GAAmB;GAAY;GAAU;EAC1E,mBAAmB;GAAC;GAAQ;GAAO;GAAmB;GAAY;GAAU;EAC7E,EACD;EACE,IAAI;EACJ,OAAO;EACP,iBAAiB;GAAC;GAAU;GAAS;GAAqB;GAAc;GAAY;EACpF,mBAAmB;GAAC;GAAU;GAAS;GAAqB;GAAc;GAAY;EACvF,CACF;CACD,SAAS,CACP;EACE,IAAI;EACJ,aAAa;EACb,eAAe;EAChB,EACD;EACE,IAAI;EACJ,aAAa;EACb,eAAe;EAChB,CACF;CACD,mBAAmB,OAAU;CAC7B,qBAAqB;CACrB,kBAAkB;CAClB,gBAAgB;CAChB,iBAAiB;CACjB,qBAAqB;CACtB;AAED,SAAgB,2BAA2B,kBAAqD;AAC9F,KAAI,CAAC,iBAAkB,QAAO;CAC9B,MAAM,aAAa,iBAAiB,aAAa,CAAC,QAAQ,WAAW,GAAG;AACxE,MAAK,MAAM,WAAW,uBAAuB,SAC3C,KAAI,QAAQ,kBAAkB,SAAS,WAAW,CAChD,QAAO,QAAQ;AAGnB,QAAO"}
@@ -0,0 +1,5 @@
1
+ //#region src/lib/personalization/device-id.d.ts
2
+ declare function getDeviceId(): string;
3
+ //#endregion
4
+ export { getDeviceId };
5
+ //# sourceMappingURL=device-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-id.d.ts","names":[],"sources":["../../../src/lib/personalization/device-id.ts"],"sourcesContent":[],"mappings":";iBAqBgB,WAAA,CAAA"}
@@ -0,0 +1,24 @@
1
+ //#region src/lib/personalization/device-id.ts
2
+ const DEVICE_ID_COOKIE = "_jg_device_id";
3
+ function buildCookieAttrs(maxAgeDays) {
4
+ return `path=/;max-age=${maxAgeDays * 24 * 60 * 60};SameSite=none;secure;domain=.justgood.win`;
5
+ }
6
+ function generateUUID() {
7
+ if (typeof crypto !== "undefined" && crypto.randomUUID) return crypto.randomUUID();
8
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
9
+ const r = Math.random() * 16 | 0;
10
+ return (c === "x" ? r : r & 3 | 8).toString(16);
11
+ });
12
+ }
13
+ function getDeviceId() {
14
+ if (typeof document === "undefined") return "";
15
+ const match = document.cookie.match(/* @__PURE__ */ new RegExp(`${DEVICE_ID_COOKIE}=([^;]+)`));
16
+ if (match && match[1]) return decodeURIComponent(match[1]);
17
+ const id = generateUUID();
18
+ document.cookie = `${DEVICE_ID_COOKIE}=${encodeURIComponent(id)};${buildCookieAttrs(90)}`;
19
+ return id;
20
+ }
21
+
22
+ //#endregion
23
+ export { getDeviceId };
24
+ //# sourceMappingURL=device-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-id.js","names":[],"sources":["../../../src/lib/personalization/device-id.ts"],"sourcesContent":["const DEVICE_ID_COOKIE = '_jg_device_id';\n\nfunction buildCookieAttrs(maxAgeDays: number): string {\n const maxAge = maxAgeDays * 24 * 60 * 60;\n if (process.env.NODE_ENV === 'production') {\n return `path=/;max-age=${maxAge};SameSite=none;secure;domain=.justgood.win`;\n }\n return `path=/;max-age=${maxAge};SameSite=Lax`;\n}\n\nfunction generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function getDeviceId(): string {\n if (typeof document === 'undefined') return '';\n const match = document.cookie.match(new RegExp(`${DEVICE_ID_COOKIE}=([^;]+)`));\n if (match && match[1]) return decodeURIComponent(match[1]);\n const id = generateUUID();\n document.cookie = `${DEVICE_ID_COOKIE}=${encodeURIComponent(id)};${buildCookieAttrs(90)}`;\n return id;\n}\n\n\n"],"mappings":";AAAA,MAAM,mBAAmB;AAEzB,SAAS,iBAAiB,YAA4B;AAGlD,QAAO,kBAFM,aAAa,KAAK,KAAK,GAEJ;;AAKpC,SAAS,eAAuB;AAC9B,KAAI,OAAO,WAAW,eAAe,OAAO,WAC1C,QAAO,OAAO,YAAY;AAE5B,QAAO,uCAAuC,QAAQ,UAAU,MAAM;EACpE,MAAM,IAAK,KAAK,QAAQ,GAAG,KAAM;AAEjC,UADU,MAAM,MAAM,IAAK,IAAI,IAAO,GAC7B,SAAS,GAAG;GACrB;;AAGJ,SAAgB,cAAsB;AACpC,KAAI,OAAO,aAAa,YAAa,QAAO;CAC5C,MAAM,QAAQ,SAAS,OAAO,sBAAM,IAAI,OAAO,GAAG,iBAAiB,UAAU,CAAC;AAC9E,KAAI,SAAS,MAAM,GAAI,QAAO,mBAAmB,MAAM,GAAG;CAC1D,MAAM,KAAK,cAAc;AACzB,UAAS,SAAS,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,CAAC,GAAG,iBAAiB,GAAG;AACvF,QAAO"}
@@ -0,0 +1,9 @@
1
+ import * as _apollo_client2 from "@apollo/client";
2
+
3
+ //#region src/lib/personalization/personalization-gql.d.ts
4
+ declare const SEND_SIGNAL_MUTATION: _apollo_client2.DocumentNode;
5
+ declare const SUBMIT_CONVERSION_MUTATION: _apollo_client2.DocumentNode;
6
+ declare const PERSONALIZE_QUERY: _apollo_client2.DocumentNode;
7
+ //#endregion
8
+ export { PERSONALIZE_QUERY, SEND_SIGNAL_MUTATION, SUBMIT_CONVERSION_MUTATION };
9
+ //# sourceMappingURL=personalization-gql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personalization-gql.d.ts","names":[],"sources":["../../../src/lib/personalization/personalization-gql.ts"],"sourcesContent":[],"mappings":";;;cAEa,sBAOZ,eAAA,CAPgC;cASpB,4BAIZ,eAAA,CAJsC;cAM1B,mBAqBZ,eAAA,CArB6B"}
@@ -0,0 +1,42 @@
1
+ import { gql } from "@apollo/client";
2
+
3
+ //#region src/lib/personalization/personalization-gql.ts
4
+ const SEND_SIGNAL_MUTATION = gql`
5
+ mutation SendSignal($input: SignalInput!) {
6
+ sendSignal(input: $input) {
7
+ success
8
+ profileUpdated
9
+ }
10
+ }
11
+ `;
12
+ const SUBMIT_CONVERSION_MUTATION = gql`
13
+ mutation SubmitConversion($input: ConversionInput!) {
14
+ submitConversion(input: $input)
15
+ }
16
+ `;
17
+ const PERSONALIZE_QUERY = gql`
18
+ query Personalize($input: SurfaceContext!, $deviceId: String!, $userId: String) {
19
+ personalize(input: $input, deviceId: $deviceId, userId: $userId) {
20
+ components {
21
+ component
22
+ contentId
23
+ propsOverrides
24
+ priority
25
+ reasoning
26
+ score
27
+ }
28
+ reasoning {
29
+ intent
30
+ confidence
31
+ factors
32
+ modelVersion
33
+ }
34
+ cacheKey
35
+ servedAt
36
+ }
37
+ }
38
+ `;
39
+
40
+ //#endregion
41
+ export { PERSONALIZE_QUERY, SEND_SIGNAL_MUTATION, SUBMIT_CONVERSION_MUTATION };
42
+ //# sourceMappingURL=personalization-gql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personalization-gql.js","names":[],"sources":["../../../src/lib/personalization/personalization-gql.ts"],"sourcesContent":["import { gql } from '@apollo/client';\n\nexport const SEND_SIGNAL_MUTATION = gql`\n mutation SendSignal($input: SignalInput!) {\n sendSignal(input: $input) {\n success\n profileUpdated\n }\n }\n`;\n\nexport const SUBMIT_CONVERSION_MUTATION = gql`\n mutation SubmitConversion($input: ConversionInput!) {\n submitConversion(input: $input)\n }\n`;\n\nexport const PERSONALIZE_QUERY = gql`\n query Personalize($input: SurfaceContext!, $deviceId: String!, $userId: String) {\n personalize(input: $input, deviceId: $deviceId, userId: $userId) {\n components {\n component\n contentId\n propsOverrides\n priority\n reasoning\n score\n }\n reasoning {\n intent\n confidence\n factors\n modelVersion\n }\n cacheKey\n servedAt\n }\n }\n`;\n\n"],"mappings":";;;AAEA,MAAa,uBAAuB,GAAG;;;;;;;;AASvC,MAAa,6BAA6B,GAAG;;;;;AAM7C,MAAa,oBAAoB,GAAG"}
@@ -1,9 +1,9 @@
1
1
  //#region src/lib/utils/imagekit.d.ts
2
- declare function getImageKitUrl(src: string, options?: {
2
+ declare function getImageKitUrl(src?: string | null, options?: {
3
3
  width?: number;
4
4
  height?: number;
5
5
  quality?: number;
6
- }): string;
6
+ }): string | undefined;
7
7
  //#endregion
8
8
  export { getImageKitUrl };
9
9
  //# sourceMappingURL=imagekit.d.ts.map
@@ -1,7 +1,7 @@
1
1
  //#region src/lib/utils/imagekit.ts
2
2
  const EXTERNAL_STORAGES = ["cdn.sanity.io", "cdn.shopify.com"];
3
3
  function getImageKitUrl(src, options) {
4
- if (!src) return src;
4
+ if (!src) return void 0;
5
5
  const normalizedEndpoint = "https://ik.imagekit.io/94rjnwlop".replace(/\/$/, "");
6
6
  if (src.includes("ik.imagekit.io")) return src;
7
7
  const params = [];
@@ -1 +1 @@
1
- {"version":3,"file":"imagekit.js","names":["params: string[]"],"sources":["../../../src/lib/utils/imagekit.ts"],"sourcesContent":["const EXTERNAL_STORAGES = [\n 'cdn.sanity.io',\n 'cdn.shopify.com',\n];\n\nexport function getImageKitUrl(\n src: string,\n options?: { width?: number; height?: number; quality?: number }\n): string {\n if (!src) return src;\n\n const publicEndpoint = 'https://ik.imagekit.io/94rjnwlop';\n const normalizedEndpoint = publicEndpoint.replace(/\\/$/, '');\n\n if (src.includes('ik.imagekit.io')) {\n return src;\n }\n\n const params: string[] = [];\n if (options?.width) params.push(`w-${options.width}`);\n if (options?.height) params.push(`h-${options.height}`);\n if (options?.quality) params.push(`q-${options.quality}`);\n params.push('f-auto');\n\n const transformStr = params.length > 0 ? `tr:${params.join(',')}` : '';\n\n if (src.startsWith('http://') || src.startsWith('https://')) {\n let urlPath = src.replace(/^https?:\\/\\//, '');\n for (const domain of EXTERNAL_STORAGES) {\n urlPath = urlPath.replace(new RegExp(`^${domain}/`), '');\n }\n return transformStr\n ? `${normalizedEndpoint}/${transformStr}/${urlPath}`\n : `${normalizedEndpoint}/${urlPath}`;\n }\n\n const normalizedSrc = src.startsWith('/') ? src.slice(1) : src;\n return transformStr\n ? `${normalizedEndpoint}/${transformStr}/${normalizedSrc}`\n : `${normalizedEndpoint}/${normalizedSrc}`;\n}\n"],"mappings":";AAAA,MAAM,oBAAoB,CACxB,iBACA,kBACD;AAED,SAAgB,eACd,KACA,SACQ;AACR,KAAI,CAAC,IAAK,QAAO;CAGjB,MAAM,qBADiB,mCACmB,QAAQ,OAAO,GAAG;AAE5D,KAAI,IAAI,SAAS,iBAAiB,CAChC,QAAO;CAGT,MAAMA,SAAmB,EAAE;AAC3B,KAAI,SAAS,MAAO,QAAO,KAAK,KAAK,QAAQ,QAAQ;AACrD,KAAI,SAAS,OAAQ,QAAO,KAAK,KAAK,QAAQ,SAAS;AACvD,KAAI,SAAS,QAAS,QAAO,KAAK,KAAK,QAAQ,UAAU;AACzD,QAAO,KAAK,SAAS;CAErB,MAAM,eAAe,OAAO,SAAS,IAAI,MAAM,OAAO,KAAK,IAAI,KAAK;AAEpE,KAAI,IAAI,WAAW,UAAU,IAAI,IAAI,WAAW,WAAW,EAAE;EAC3D,IAAI,UAAU,IAAI,QAAQ,gBAAgB,GAAG;AAC7C,OAAK,MAAM,UAAU,kBACnB,WAAU,QAAQ,wBAAQ,IAAI,OAAO,IAAI,OAAO,GAAG,EAAE,GAAG;AAE1D,SAAO,eACH,GAAG,mBAAmB,GAAG,aAAa,GAAG,YACzC,GAAG,mBAAmB,GAAG;;CAG/B,MAAM,gBAAgB,IAAI,WAAW,IAAI,GAAG,IAAI,MAAM,EAAE,GAAG;AAC3D,QAAO,eACH,GAAG,mBAAmB,GAAG,aAAa,GAAG,kBACzC,GAAG,mBAAmB,GAAG"}
1
+ {"version":3,"file":"imagekit.js","names":["params: string[]"],"sources":["../../../src/lib/utils/imagekit.ts"],"sourcesContent":["const EXTERNAL_STORAGES = [\n 'cdn.sanity.io',\n 'cdn.shopify.com',\n];\n\nexport function getImageKitUrl(\n src?: string | null,\n options?: { width?: number; height?: number; quality?: number }\n): string | undefined {\n if (!src) return undefined;\n\n const publicEndpoint = 'https://ik.imagekit.io/94rjnwlop';\n const normalizedEndpoint = publicEndpoint.replace(/\\/$/, '');\n\n if (src.includes('ik.imagekit.io')) {\n return src;\n }\n\n const params: string[] = [];\n if (options?.width) params.push(`w-${options.width}`);\n if (options?.height) params.push(`h-${options.height}`);\n if (options?.quality) params.push(`q-${options.quality}`);\n params.push('f-auto');\n\n const transformStr = params.length > 0 ? `tr:${params.join(',')}` : '';\n\n if (src.startsWith('http://') || src.startsWith('https://')) {\n let urlPath = src.replace(/^https?:\\/\\//, '');\n for (const domain of EXTERNAL_STORAGES) {\n urlPath = urlPath.replace(new RegExp(`^${domain}/`), '');\n }\n return transformStr\n ? `${normalizedEndpoint}/${transformStr}/${urlPath}`\n : `${normalizedEndpoint}/${urlPath}`;\n }\n\n const normalizedSrc = src.startsWith('/') ? src.slice(1) : src;\n return transformStr\n ? `${normalizedEndpoint}/${transformStr}/${normalizedSrc}`\n : `${normalizedEndpoint}/${normalizedSrc}`;\n}\n"],"mappings":";AAAA,MAAM,oBAAoB,CACxB,iBACA,kBACD;AAED,SAAgB,eACd,KACA,SACoB;AACpB,KAAI,CAAC,IAAK,QAAO;CAGjB,MAAM,qBADiB,mCACmB,QAAQ,OAAO,GAAG;AAE5D,KAAI,IAAI,SAAS,iBAAiB,CAChC,QAAO;CAGT,MAAMA,SAAmB,EAAE;AAC3B,KAAI,SAAS,MAAO,QAAO,KAAK,KAAK,QAAQ,QAAQ;AACrD,KAAI,SAAS,OAAQ,QAAO,KAAK,KAAK,QAAQ,SAAS;AACvD,KAAI,SAAS,QAAS,QAAO,KAAK,KAAK,QAAQ,UAAU;AACzD,QAAO,KAAK,SAAS;CAErB,MAAM,eAAe,OAAO,SAAS,IAAI,MAAM,OAAO,KAAK,IAAI,KAAK;AAEpE,KAAI,IAAI,WAAW,UAAU,IAAI,IAAI,WAAW,WAAW,EAAE;EAC3D,IAAI,UAAU,IAAI,QAAQ,gBAAgB,GAAG;AAC7C,OAAK,MAAM,UAAU,kBACnB,WAAU,QAAQ,wBAAQ,IAAI,OAAO,IAAI,OAAO,GAAG,EAAE,GAAG;AAE1D,SAAO,eACH,GAAG,mBAAmB,GAAG,aAAa,GAAG,YACzC,GAAG,mBAAmB,GAAG;;CAG/B,MAAM,gBAAgB,IAAI,WAAW,IAAI,GAAG,IAAI,MAAM,EAAE,GAAG;AAC3D,QAAO,eACH,GAAG,mBAAmB,GAAG,aAAa,GAAG,kBACzC,GAAG,mBAAmB,GAAG"}