@envive-ai/react-hooks 0.1.3 → 0.1.4

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 (428) hide show
  1. package/dist/adapters/amplitude/index.cjs +13 -13
  2. package/dist/adapters/amplitude/index.d.cts +5 -3
  3. package/dist/adapters/amplitude/index.d.ts +5 -3
  4. package/dist/adapters/amplitude/index.js +10 -10
  5. package/dist/api-B2euFL-5.cjs +269 -0
  6. package/dist/api-XRr_lAG6.js +190 -0
  7. package/dist/application/config/index.cjs +14 -5
  8. package/dist/application/config/index.d.cts +2 -1
  9. package/dist/application/config/index.d.ts +2 -1
  10. package/dist/application/config/index.js +14 -5
  11. package/dist/application/models/graphql/index.cjs +12 -12
  12. package/dist/application/models/graphql/index.d.cts +1 -1
  13. package/dist/application/models/graphql/index.d.ts +1 -1
  14. package/dist/application/models/graphql/index.js +10 -10
  15. package/dist/application/models/guards/api/index.cjs +2 -2
  16. package/dist/application/models/guards/api/index.d.cts +2 -2
  17. package/dist/application/models/guards/api/index.d.ts +2 -2
  18. package/dist/application/models/guards/api/index.js +2 -2
  19. package/dist/application/models/index.cjs +54 -54
  20. package/dist/application/models/index.d.cts +8 -9
  21. package/dist/application/models/index.d.ts +8 -9
  22. package/dist/application/models/index.js +10 -10
  23. package/dist/application/models/utilityTypes/index.cjs +1 -1
  24. package/dist/application/models/utilityTypes/index.d.cts +1 -1
  25. package/dist/application/models/utilityTypes/index.d.ts +1 -1
  26. package/dist/application/models/utilityTypes/index.js +1 -1
  27. package/dist/application/models/variantInfo/index.cjs +1 -1
  28. package/dist/application/models/variantInfo/index.d.cts +1 -1
  29. package/dist/application/models/variantInfo/index.d.ts +1 -1
  30. package/dist/application/models/variantInfo/index.js +1 -1
  31. package/dist/application/service/customerService/index.cjs +2 -2
  32. package/dist/application/service/customerService/index.d.cts +2 -2
  33. package/dist/application/service/customerService/index.d.ts +2 -2
  34. package/dist/application/service/customerService/index.js +2 -2
  35. package/dist/application/service/index.cjs +37 -757
  36. package/dist/application/service/index.d.cts +14 -22
  37. package/dist/application/service/index.d.ts +14 -22
  38. package/dist/application/service/index.js +12 -727
  39. package/dist/application/utils/index.cjs +37 -37
  40. package/dist/application/utils/index.d.cts +13 -13
  41. package/dist/application/utils/index.d.ts +12 -12
  42. package/dist/application/utils/index.js +10 -10
  43. package/dist/atomStore-B1cgmbP0.js +32 -0
  44. package/dist/atomStore-JwGb7pcy.cjs +58 -0
  45. package/dist/atoms/app/index.cjs +16 -16
  46. package/dist/atoms/app/index.d.cts +11 -11
  47. package/dist/atoms/app/index.d.ts +12 -12
  48. package/dist/atoms/app/index.js +10 -10
  49. package/dist/atoms/atomStore/index.cjs +1 -2
  50. package/dist/atoms/atomStore/index.d.cts +2 -1
  51. package/dist/atoms/atomStore/index.d.ts +2 -1
  52. package/dist/atoms/atomStore/index.js +1 -2
  53. package/dist/atoms/chat/index.cjs +40 -40
  54. package/dist/atoms/chat/index.d.cts +37 -37
  55. package/dist/atoms/chat/index.d.ts +38 -38
  56. package/dist/atoms/chat/index.js +10 -10
  57. package/dist/atoms/globalSearch/index.cjs +1 -1
  58. package/dist/atoms/globalSearch/index.d.cts +7 -6
  59. package/dist/atoms/globalSearch/index.d.ts +7 -6
  60. package/dist/atoms/globalSearch/index.js +1 -1
  61. package/dist/atoms/org/index.cjs +37 -40
  62. package/dist/atoms/org/index.d.cts +32 -53
  63. package/dist/atoms/org/index.d.ts +31 -52
  64. package/dist/atoms/org/index.js +11 -12
  65. package/dist/atoms/search/index.cjs +41 -43
  66. package/dist/atoms/search/index.d.cts +9 -10
  67. package/dist/atoms/search/index.d.ts +9 -10
  68. package/dist/atoms/search/index.js +10 -12
  69. package/dist/bandolier-B76-OE75.cjs +1230 -0
  70. package/dist/bandolier-DRn_x1g1.js +1230 -0
  71. package/dist/carpe-kHi4RLB5.cjs +608 -0
  72. package/dist/carpe-qrSU99gq.js +606 -0
  73. package/dist/{chat-CCgyDehy.cjs → chat-BgONoYU7.cjs} +2 -1
  74. package/dist/chat-CLJ4NWcN.js +26 -0
  75. package/dist/{components-CScS7Ii-.cjs → components-BKZbet67.cjs} +2 -1
  76. package/dist/components-CV1fhAkj.js +11 -0
  77. package/dist/config/locators/components/chat/index.cjs +1 -1
  78. package/dist/config/locators/components/chat/index.d.cts +1 -1
  79. package/dist/config/locators/components/chat/index.d.ts +1 -1
  80. package/dist/config/locators/components/chat/index.js +1 -1
  81. package/dist/config/locators/components/chat/variants/index.cjs +2 -1
  82. package/dist/config/locators/components/chat/variants/index.d.cts +2 -1
  83. package/dist/config/locators/components/chat/variants/index.d.ts +2 -1
  84. package/dist/config/locators/components/chat/variants/index.js +2 -1
  85. package/dist/config/locators/components/index.cjs +1 -1
  86. package/dist/config/locators/components/index.d.cts +1 -1
  87. package/dist/config/locators/components/index.d.ts +1 -1
  88. package/dist/config/locators/components/index.js +1 -1
  89. package/dist/config/locators/components/search/index.cjs +2 -1
  90. package/dist/config/locators/components/search/index.d.cts +2 -1
  91. package/dist/config/locators/components/search/index.d.ts +2 -1
  92. package/dist/config/locators/components/search/index.js +2 -1
  93. package/dist/config/locators/index.cjs +4 -4
  94. package/dist/config/locators/index.d.cts +4 -3
  95. package/dist/config/locators/index.d.ts +4 -3
  96. package/dist/config/locators/index.js +4 -4
  97. package/dist/contexts/index.cjs +20 -23
  98. package/dist/contexts/index.d.cts +38 -19
  99. package/dist/contexts/index.d.ts +41 -22
  100. package/dist/contexts/index.js +11 -17
  101. package/dist/contexts-CQDwe3rK.cjs +14333 -0
  102. package/dist/contexts-e2sM-B9g.js +12919 -0
  103. package/dist/coterie-mMirPcHP.js +240 -0
  104. package/dist/coterie-yQ-_JXSw.cjs +240 -0
  105. package/dist/customerService-BG1uNZZ1.cjs +36 -0
  106. package/dist/customerService-BHQRnLhC.js +23 -0
  107. package/dist/custservice-types-C83itZmy.cjs +35 -0
  108. package/dist/custservice-types-DPQ-4TI6.js +23 -0
  109. package/dist/default-8Jfv8ehQ.cjs +199 -0
  110. package/dist/default-C8PQf-38.js +176 -0
  111. package/dist/default-LukSiCz1.js +4 -0
  112. package/dist/default-rJSJ887P.cjs +4 -0
  113. package/dist/divIds-CWkntTsx.js +23 -0
  114. package/dist/{divIds-CFyAjjp3.cjs → divIds-DEL_-qU0.cjs} +2 -1
  115. package/dist/dreamlandBaby-DHltv12Z.cjs +347 -0
  116. package/dist/dreamlandBaby-cG0HM9bt.js +347 -0
  117. package/dist/{embedded-BlXJUbik.cjs → embedded--2L0F4b5.cjs} +2 -1
  118. package/dist/embedded-C5uJqmuD.js +23 -0
  119. package/dist/entrypoints-CNUvSgnk.js +7 -0
  120. package/dist/entrypoints-DM9Sm18O.cjs +19 -0
  121. package/dist/events/index.cjs +1 -1
  122. package/dist/events/index.d.cts +2 -1
  123. package/dist/events/index.d.ts +2 -1
  124. package/dist/events/index.js +1 -1
  125. package/dist/events-ClCDFK7t.js +78 -0
  126. package/dist/events-Da7gpmGv.cjs +90 -0
  127. package/dist/featureFlagService-5wdmW02z.d.ts +18 -0
  128. package/dist/featureFlagService-DaelrXEk.d.cts +18 -0
  129. package/dist/fiveCbd-Cvnwh03g.cjs +614 -0
  130. package/dist/fiveCbd-DhYMlsf9.js +614 -0
  131. package/dist/forLoveAndLemons-C8DuUexW.js +666 -0
  132. package/dist/forLoveAndLemons-DR6a1zjJ.cjs +668 -0
  133. package/dist/{globalSearch-hxbXekus.cjs → globalSearch-BTeZxvk1.cjs} +2 -1
  134. package/dist/globalSearch-b0wC7ZEO.js +14 -0
  135. package/dist/greenpan-B4Pu65kV.js +398 -0
  136. package/dist/greenpan-BL5p6j7f.cjs +398 -0
  137. package/dist/grooveLife-DjKWHoN3.cjs +343 -0
  138. package/dist/grooveLife-JK0TyaPz.js +343 -0
  139. package/dist/homegrownCannabis-DxqSDkmS.js +411 -0
  140. package/dist/homegrownCannabis-ZnfCqW-m.cjs +411 -0
  141. package/dist/hooks/index.cjs +38 -38
  142. package/dist/hooks/index.d.cts +25 -16
  143. package/dist/hooks/index.d.ts +30 -21
  144. package/dist/hooks/index.js +11 -17
  145. package/dist/index-BTK5uzs6.d.cts +98 -0
  146. package/dist/index-BfuO9b0Q.d.ts +749 -0
  147. package/dist/index-BzgkfbNO.d.cts +228 -0
  148. package/dist/index-C62lPpy4.d.cts +25 -0
  149. package/dist/index-CExtydIH.d.ts +9 -0
  150. package/dist/index-CKKkTsms.d.ts +39 -0
  151. package/dist/index-CNsGWfS6.d.cts +749 -0
  152. package/dist/index-CYtsPztZ.d.cts +203 -0
  153. package/dist/index-C_C0tLeD.d.ts +203 -0
  154. package/dist/index-ClJ0nMsR.d.cts +184 -0
  155. package/dist/index-Cx9e-fRi.d.ts +184 -0
  156. package/dist/index-D2VaMPA3.d.ts +98 -0
  157. package/dist/index-D46Rd0io.d.cts +39 -0
  158. package/dist/index-DFL1dIT_.d.ts +7 -0
  159. package/dist/index-DPx8s5YH.d.ts +25 -0
  160. package/dist/index-Dxpscrvz.d.ts +228 -0
  161. package/dist/index-MFbPQ8Ji.d.ts +95 -0
  162. package/dist/index-VSFakgAI.d.cts +95 -0
  163. package/dist/index-jBATkcc_.d.cts +9 -0
  164. package/dist/index-zZjcds15.d.cts +7 -0
  165. package/dist/interceptors/index.cjs +12 -13
  166. package/dist/interceptors/index.d.cts +10 -10
  167. package/dist/interceptors/index.d.ts +10 -10
  168. package/dist/interceptors/index.js +10 -11
  169. package/dist/jackArcher-CXf_IAmC.js +728 -0
  170. package/dist/jackArcher-mGkojXek.cjs +728 -0
  171. package/dist/jordanCraig-BvCvPRoR.js +1787 -0
  172. package/dist/jordanCraig-Dv8pVCiS.cjs +1787 -0
  173. package/dist/kindredBravely-UQP7wiNu.cjs +491 -0
  174. package/dist/kindredBravely-X8F_LNph.js +491 -0
  175. package/dist/kutFromTheKloth-BhYKk3CN.cjs +370 -0
  176. package/dist/kutFromTheKloth-D1xsTSJr.js +370 -0
  177. package/dist/larryAndSerges-1411NuZa.cjs +262 -0
  178. package/dist/larryAndSerges-DVIRLItu.js +262 -0
  179. package/dist/leapsAndRebounds-BJ8mwr33.js +361 -0
  180. package/dist/leapsAndRebounds-UcP9EJVO.cjs +361 -0
  181. package/dist/logger-Dln20ans.cjs +26 -0
  182. package/dist/logger-pdEEY8T2.js +20 -0
  183. package/dist/longevityrx-BFSv9GF5.cjs +321 -0
  184. package/dist/longevityrx-Cp6wleWr.js +321 -0
  185. package/dist/lookOptic-BGhU4910.js +283 -0
  186. package/dist/lookOptic-KieSqskd.cjs +283 -0
  187. package/dist/mantraBrand-CHQw-0nw.cjs +751 -0
  188. package/dist/mantraBrand-DrqG9uqO.js +751 -0
  189. package/dist/medterra-CLG6Co1C.cjs +584 -0
  190. package/dist/medterra-D8ZX9NZC.js +584 -0
  191. package/dist/modells-BzyPwN2m.cjs +485 -0
  192. package/dist/modells-CAfqOCW4.js +485 -0
  193. package/dist/nodeSelector-B3bPtEjX.d.cts +31 -0
  194. package/dist/nodeSelector-BiCDowlK.d.ts +31 -0
  195. package/dist/orgConfigResults--dAwtw3W.d.ts +881 -0
  196. package/dist/orgConfigResults-BL0XBA6x.d.cts +881 -0
  197. package/dist/pressedFloral-DULBuQwR.cjs +662 -0
  198. package/dist/pressedFloral-Dp-7Fk3S.js +662 -0
  199. package/dist/search-filter-types-BNTLVXqQ.d.cts +102 -0
  200. package/dist/search-filter-types-DkmH1TxJ.d.ts +102 -0
  201. package/dist/skinPerfection-BxuYCeJX.js +335 -0
  202. package/dist/skinPerfection-Cd3XZ6By.cjs +335 -0
  203. package/dist/snapSupplements-Bf6htPM0.js +286 -0
  204. package/dist/snapSupplements-ZFnXyMuZ.cjs +286 -0
  205. package/dist/socialProofClasses-DdzG1tZy.js +10 -0
  206. package/dist/socialProofClasses-ky69yppk.cjs +40 -0
  207. package/dist/spanx-CwDPQaGj.js +662 -0
  208. package/dist/spanx-Cyd4qDlK.cjs +664 -0
  209. package/dist/spanxStaging-D43nyAGy.js +846 -0
  210. package/dist/spanxStaging-ijbYnHzr.cjs +849 -0
  211. package/dist/suggestionBarV2-types-CwOXzIKq.js +10 -0
  212. package/dist/{suggestionBarV2-types-DG3Ekk44.cjs → suggestionBarV2-types-Dc4-zJlV.cjs} +2 -1
  213. package/dist/supergoop-BnbFG7hm.cjs +338 -0
  214. package/dist/supergoop-CY043wIg.js +336 -0
  215. package/dist/test-types-CXVJxTeu.d.ts +40 -0
  216. package/dist/test-types-CuOq25VT.d.cts +40 -0
  217. package/dist/types/index.cjs +2 -2
  218. package/dist/types/index.d.cts +2 -2
  219. package/dist/types/index.d.ts +2 -2
  220. package/dist/types/index.js +2 -2
  221. package/dist/types-BF_CJeck.js +177 -0
  222. package/dist/types-CD4LFta-.d.cts +33 -0
  223. package/dist/types-CNH4sfF-.cjs +231 -0
  224. package/dist/types-DBdI0j89.d.ts +33 -0
  225. package/dist/uniqueVintage-Cui74mlJ.js +1212 -0
  226. package/dist/uniqueVintage-R2Jcu1y1.cjs +1214 -0
  227. package/dist/variant-CKVRF2-W.d.ts +13 -0
  228. package/dist/variant-raYuOP4L.d.cts +13 -0
  229. package/dist/venaCbd-o5_vOp4e.js +366 -0
  230. package/dist/venaCbd-r-IxEVc1.cjs +366 -0
  231. package/dist/westonJonBoucher-C95EuCl-.js +423 -0
  232. package/dist/westonJonBoucher-DjGEW3ZB.cjs +423 -0
  233. package/dist/wineEnthusiast-DeTFY8Gm.js +941 -0
  234. package/dist/wineEnthusiast-DvfcV5B3.cjs +941 -0
  235. package/dist/wolfMattress-6xPfOJt3.js +373 -0
  236. package/dist/wolfMattress-BjGnGKjP.cjs +373 -0
  237. package/dist/wolfTactical-Bi3WZu0m.cjs +350 -0
  238. package/dist/wolfTactical-C_F9-oPX.js +350 -0
  239. package/package.json +1 -1
  240. package/src/adapters/amplitude/amplitudeAdapter.ts +32 -9
  241. package/src/adapters/spiffy/commerce/api.ts +17 -8
  242. package/src/adapters/spiffy/commerce/graphql.ts +16 -5
  243. package/src/application/config/generalStaticConfig.ts +5 -2
  244. package/src/application/models/api/orgConfigResults.ts +6 -2
  245. package/src/application/models/validators/validateGraphQLColorsConfig.ts +23 -21
  246. package/src/application/service/cdnService.ts +4 -2
  247. package/src/application/service/index.ts +0 -1
  248. package/src/application/service/pageVariantService.ts +5 -5
  249. package/src/application/service/searchService.ts +9 -2
  250. package/src/application/service/windowChatToggleService.ts +28 -19
  251. package/src/application/service/windowFrontendConfigService.ts +7 -4
  252. package/src/atoms/app/index.ts +26 -17
  253. package/src/atoms/app/variant.ts +1 -0
  254. package/src/atoms/chat/messageQueue.ts +1 -1
  255. package/src/atoms/envive/enviveConfig.ts +81 -0
  256. package/src/atoms/org/graphqlConfig.ts +29 -11
  257. package/src/atoms/org/merchantCss.ts +114 -0
  258. package/src/atoms/org/org.ts +101 -64
  259. package/src/atoms/org/orgPageConfig.ts +9 -6
  260. package/src/atoms/org/orgUIConfig.ts +22 -9
  261. package/src/atoms/search/chatSearch.ts +85 -67
  262. package/src/contexts/chatContext.tsx +4 -1
  263. package/src/contexts/enviveConfigContext.tsx +37 -26
  264. package/src/contexts/enviveCssContext.tsx +20 -0
  265. package/src/contexts/index.ts +2 -0
  266. package/src/contexts/orgConfigContext.tsx +106 -0
  267. package/src/contexts/systemSettingsContext.tsx +2 -2
  268. package/src/contexts/types.ts +12 -9
  269. package/src/hooks/index.ts +1 -0
  270. package/src/hooks/useSearch.tsx +10 -6
  271. package/src/hooks/utils.ts +1 -1
  272. package/src/interceptors/useFormEscalation.ts +26 -9
  273. package/src/types.ts +0 -2
  274. package/dist/api-BtzLHcfU.cjs +0 -268
  275. package/dist/api-kpPTZhV9.js +0 -189
  276. package/dist/atomStore-BNQyGmU_.cjs +0 -57
  277. package/dist/atomStore-TnLPtYns.js +0 -31
  278. package/dist/bandolier-CQrxBHsk.cjs +0 -1230
  279. package/dist/bandolier-Di9DpZ8e.js +0 -1230
  280. package/dist/carpe-3NJOR-Rj.cjs +0 -608
  281. package/dist/carpe-DmWKaIQq.js +0 -606
  282. package/dist/cdnService-BNreZjqy.js +0 -18
  283. package/dist/cdnService-vLxePdrU.cjs +0 -23
  284. package/dist/chat-CCQMmhc1.cjs +0 -5057
  285. package/dist/chat-Dk6KPb1K.js +0 -25
  286. package/dist/chat-H6YcCS4I.js +0 -4113
  287. package/dist/components-DAQxVIn9.js +0 -10
  288. package/dist/coterie-D0UFsFC5.cjs +0 -240
  289. package/dist/coterie-JblRmIZL.js +0 -240
  290. package/dist/customerService-C4wc0glQ.js +0 -22
  291. package/dist/customerService-zsDlp7g2.cjs +0 -35
  292. package/dist/custservice-types-D8Npo-5Z.js +0 -22
  293. package/dist/custservice-types-E9_OSaZ7.cjs +0 -34
  294. package/dist/default-C5ZTV8HA.cjs +0 -4
  295. package/dist/default-DPv8m-eQ.js +0 -175
  296. package/dist/default-DRKBosow.cjs +0 -198
  297. package/dist/default-ao0vRl0W.js +0 -4
  298. package/dist/divIds-BWvq-i6I.js +0 -22
  299. package/dist/dreamlandBaby-CyS8oW8X.js +0 -347
  300. package/dist/dreamlandBaby-y7kSvwH2.cjs +0 -347
  301. package/dist/embedded-C1jvFj3v.js +0 -22
  302. package/dist/entrypoints-CmmOszXO.js +0 -6
  303. package/dist/entrypoints-fowCLUT2.cjs +0 -18
  304. package/dist/enviveConfigContext-Bs8kepnO.cjs +0 -48
  305. package/dist/enviveConfigContext-CWVdVWKW.js +0 -34
  306. package/dist/events-DgFzlVJR.js +0 -77
  307. package/dist/events-bH-24eRW.cjs +0 -89
  308. package/dist/featureFlagService-CroFRxvD.d.cts +0 -17
  309. package/dist/featureFlagService-NkJ2fuEj.d.ts +0 -17
  310. package/dist/featureGates-BMWXU0dS.d.ts +0 -90
  311. package/dist/featureGates-N_gyHCTn.d.cts +0 -90
  312. package/dist/fiveCbd-CXVuIBiZ.cjs +0 -614
  313. package/dist/fiveCbd-Cyc3-Ab9.js +0 -614
  314. package/dist/forLoveAndLemons-CxQS0USq.cjs +0 -668
  315. package/dist/forLoveAndLemons-D8mcgmdk.js +0 -666
  316. package/dist/frontendConfig-KeNqU1wa.d.cts +0 -790
  317. package/dist/frontendConfig-cPvCTWm6.d.ts +0 -790
  318. package/dist/globalSearch-BC0rOX3E.js +0 -13
  319. package/dist/greenpan-JM6SHcqO.js +0 -398
  320. package/dist/greenpan-eIzyxVsn.cjs +0 -398
  321. package/dist/grooveLife-BmsUc2cD.js +0 -343
  322. package/dist/grooveLife-KdTizVUn.cjs +0 -343
  323. package/dist/homegrownCannabis-C0GDai4r.cjs +0 -411
  324. package/dist/homegrownCannabis-a9udocBT.js +0 -411
  325. package/dist/hooks-DjOa7ihH.cjs +0 -7331
  326. package/dist/hooks-fneW8SWw.js +0 -7152
  327. package/dist/index-BQErGgfM.d.cts +0 -202
  328. package/dist/index-BdNKc2ix.d.cts +0 -8
  329. package/dist/index-BrXuc_Ck.d.cts +0 -24
  330. package/dist/index-C4zjAR1c.d.cts +0 -227
  331. package/dist/index-CGB6CAmr.d.ts +0 -6
  332. package/dist/index-CIco0cCQ.d.ts +0 -183
  333. package/dist/index-COG1kOZG.d.ts +0 -749
  334. package/dist/index-CVxe7FpL.d.cts +0 -6
  335. package/dist/index-Cn1SeI5y.d.cts +0 -183
  336. package/dist/index-CnqHN_jz.d.ts +0 -202
  337. package/dist/index-Cqg6ltII.d.ts +0 -38
  338. package/dist/index-DE_7Q8qK.d.ts +0 -94
  339. package/dist/index-Da0UzyI9.d.ts +0 -24
  340. package/dist/index-DbWWcYax.d.cts +0 -749
  341. package/dist/index-DtoVXd6O.d.cts +0 -97
  342. package/dist/index-JClBRnSX.d.cts +0 -94
  343. package/dist/index-ghzD_356.d.ts +0 -8
  344. package/dist/index-hdbCEjYy.d.cts +0 -38
  345. package/dist/index-luJrHgPN.d.ts +0 -97
  346. package/dist/index-tfRj22E1.d.ts +0 -227
  347. package/dist/jackArcher-B6OJ0N3a.cjs +0 -728
  348. package/dist/jackArcher-B9fe4Hv8.js +0 -728
  349. package/dist/jordanCraig-0CB_m_ts.cjs +0 -1787
  350. package/dist/jordanCraig-DNm1iw1L.js +0 -1787
  351. package/dist/kindredBravely-CZgt7DJA.js +0 -491
  352. package/dist/kindredBravely-KvYPbckZ.cjs +0 -491
  353. package/dist/kutFromTheKloth-BxgtWZs9.cjs +0 -370
  354. package/dist/kutFromTheKloth-SmteSZjk.js +0 -370
  355. package/dist/larryAndSerges-6O_u3L90.cjs +0 -261
  356. package/dist/larryAndSerges-DO-zG8ES.js +0 -261
  357. package/dist/leapsAndRebounds-BK62AmXw.js +0 -361
  358. package/dist/leapsAndRebounds-gPsWVUmQ.cjs +0 -361
  359. package/dist/logger-Be0NyKaY.cjs +0 -25
  360. package/dist/logger-BexDfK3W.js +0 -19
  361. package/dist/longevityrx-DjKbwJo3.cjs +0 -321
  362. package/dist/longevityrx-eq5TeUcy.js +0 -321
  363. package/dist/lookOptic-BPPqms_j.cjs +0 -283
  364. package/dist/lookOptic-jRpBXQCN.js +0 -283
  365. package/dist/mantraBrand-BZOZfkUK.js +0 -751
  366. package/dist/mantraBrand-Cp8zptkj.cjs +0 -751
  367. package/dist/medterra-BHYCBgvQ.cjs +0 -584
  368. package/dist/medterra-CShe6CLY.js +0 -584
  369. package/dist/modells-DE7-gmjK.cjs +0 -485
  370. package/dist/modells-DFyJxNwT.js +0 -485
  371. package/dist/nodeSelector-DpKXszfU.d.ts +0 -30
  372. package/dist/nodeSelector-vKB44CDB.d.cts +0 -30
  373. package/dist/org-Bkn6fl6I.cjs +0 -106
  374. package/dist/org-CX8HFbc9.js +0 -63
  375. package/dist/pressedFloral-BMkCVs8c.cjs +0 -662
  376. package/dist/pressedFloral-aK9br-LF.js +0 -662
  377. package/dist/search-DtIFZeMA.cjs +0 -743
  378. package/dist/search-eWwg8pNn.js +0 -542
  379. package/dist/search-filter-types-ByJnFPc4.d.cts +0 -101
  380. package/dist/search-filter-types-DPgeG8FS.d.ts +0 -101
  381. package/dist/skinPerfection-B9G6yLM2.js +0 -335
  382. package/dist/skinPerfection-BBC1q65Z.cjs +0 -335
  383. package/dist/snapSupplements-D7hx6Kgj.cjs +0 -286
  384. package/dist/snapSupplements-DKvJl__T.js +0 -286
  385. package/dist/socialProofClasses-BYLiEXpU.cjs +0 -39
  386. package/dist/socialProofClasses-CkJufEGb.js +0 -9
  387. package/dist/spanx-D-ZKkxjM.cjs +0 -664
  388. package/dist/spanx-yl7YfVrf.js +0 -662
  389. package/dist/spanxStaging-CXeIg6zI.cjs +0 -849
  390. package/dist/spanxStaging-DzGXL9wD.js +0 -846
  391. package/dist/suggestionBarV2-types-B0RbMStE.js +0 -9
  392. package/dist/supergoop-CSpDPOpl.cjs +0 -337
  393. package/dist/supergoop-D0UkuRiA.js +0 -335
  394. package/dist/test-types-C9b_OdfO.d.ts +0 -39
  395. package/dist/test-types-CpKCxk8U.d.cts +0 -39
  396. package/dist/types-BE4faOO_.d.cts +0 -32
  397. package/dist/types-C3S1H4hl.js +0 -176
  398. package/dist/types-TD8g7LnH.d.ts +0 -32
  399. package/dist/types-lcjuhDBt.cjs +0 -230
  400. package/dist/uniqueVintage-DygVpCqU.cjs +0 -1214
  401. package/dist/uniqueVintage-_n0FZFVj.js +0 -1212
  402. package/dist/useMessageInterceptor-BP6gzo8a.js +0 -57
  403. package/dist/useMessageInterceptor-BnUG2Pzt.cjs +0 -72
  404. package/dist/variant-DH4zusMi.d.cts +0 -12
  405. package/dist/variant-DTEqSBHd.d.ts +0 -12
  406. package/dist/variantInfo-BTvC6CQh.js +0 -1
  407. package/dist/variantInfo-Cz2YXraO.cjs +0 -0
  408. package/dist/venaCbd-BS0dvdBm.js +0 -366
  409. package/dist/venaCbd-Pqg0bj-P.cjs +0 -366
  410. package/dist/westonJonBoucher-CLw8Hy6u.js +0 -423
  411. package/dist/westonJonBoucher-CeA0jwxe.cjs +0 -423
  412. package/dist/wineEnthusiast-M9P18d1w.js +0 -941
  413. package/dist/wineEnthusiast-gHBaQMbe.cjs +0 -941
  414. package/dist/wolfMattress-BQHjoQYu.js +0 -373
  415. package/dist/wolfMattress-CdmN-Evm.cjs +0 -373
  416. package/dist/wolfTactical-Cc2ZLBRh.js +0 -350
  417. package/dist/wolfTactical-dObnPgAG.cjs +0 -350
  418. package/src/application/service/environmentService.ts +0 -51
  419. package/src/extension.ts +0 -63
  420. package/src/initialize.ts +0 -163
  421. package/src/main.tsx +0 -108
  422. package/src/merchants/uniqueVintage/views/useUniqueVintageChatSearch.ts +0 -147
  423. /package/dist/{atomStore-FSZd_20F.js → locators-Dc5ZT0aF.js} +0 -0
  424. /package/dist/{atomStore-B3tsg6mF.cjs → locators-lQMJj830.cjs} +0 -0
  425. /package/dist/{locators-C2DX_nX6.js → utilityTypes-BVikejDo.js} +0 -0
  426. /package/dist/{locators-CUpyd9Wt.cjs → utilityTypes-C4h2wgAK.cjs} +0 -0
  427. /package/dist/{utilityTypes-DMdsI0DG.cjs → variantInfo-CNRTY0gH.cjs} +0 -0
  428. /package/dist/{utilityTypes-UWdNHElu.js → variantInfo-CzhR5W6h.js} +0 -0
@@ -1,4113 +0,0 @@
1
- import { EventsDispatcher, SpiffyEvent } from "./events-DgFzlVJR.js";
2
- import { logger_default } from "./logger-BexDfK3W.js";
3
- import { ColorNames, CustomerServiceIntegrationMode, OrgShortName, PageVariantTestType, getOrgInfo } from "./types-C3S1H4hl.js";
4
- import { useEnviveConfig } from "./enviveConfigContext-CWVdVWKW.js";
5
- import { getAtomStore, sessionStorageUtil } from "./atomStore-TnLPtYns.js";
6
- import { hasPropertyOfType, isApiPDPAttributes, isApiProductResponseAttributes, isApiProductSearchResponseAttributes, isApiQueryTypedAttributes, isApiResponse, isApiReviewResponseAttributes, isApiSearchAttributes, isApiSuggestionClickedAttributes, isApiTextResponseAttributes, isApiUserEvent, isSuggestion } from "./api-kpPTZhV9.js";
7
- import { findCustomerServiceImpl } from "./customerService-C4wc0glQ.js";
8
- import { atom } from "jotai";
9
- import { UserEventCategory } from "@spiffy-ai/commerce-api-client/dist/models/UserEventCategory";
10
- import { createInstance } from "@amplitude/analytics-browser";
11
- import { Configuration, ContextEnvEnum, ContextSourceEnum, CustomerServiceApi, DefaultApi, FormType, FulfillmentDisplayStatus, InferenceApi, OrganizationStatusEnum, PLPAttributeCategory, PageVisitCategory, ResponseCategory, ResponseError, SupportedEventProductCategory, UserEventCategory as UserEventCategory$1, V1OrgConfigGetSourceEnum } from "@spiffy-ai/commerce-api-client";
12
- import { atomWithStorage, createJSONStorage } from "jotai/utils";
13
- import { createPortal } from "react-dom";
14
- import UAParser from "ua-parser-js";
15
- import { v4 } from "uuid";
16
-
17
- //#region src/application/models/featureGates.ts
18
- let FeatureGates = /* @__PURE__ */ function(FeatureGates$1) {
19
- FeatureGates$1["IsClientSessionEnabled"] = "is_client_session_enabled";
20
- FeatureGates$1["IsNewFeatureEnabled"] = "is_new_feature_enabled";
21
- FeatureGates$1["IsFineTunedModel8b"] = "is_fine_tuned_model_8b";
22
- FeatureGates$1["IsIntegratedCXEnabled"] = "is_integrated_cx_enabled";
23
- FeatureGates$1["IsNonShapewearEnabled"] = "is_non_shapewear_enabled";
24
- FeatureGates$1["IsImageBannerEnabled"] = "is_image_banner_enabled";
25
- FeatureGates$1["IsOrderLookupEnabled"] = "is_order_lookup_enabled";
26
- FeatureGates$1["IsSummarizeReviewsEnabled"] = "is_summarize_reviews_enabled";
27
- FeatureGates$1["IsGlobalSearchEnabled"] = "is_global_search_enabled";
28
- FeatureGates$1["IsImagePromptEnabled"] = "is_image_prompt_enabled";
29
- FeatureGates$1["IsWatermarkEnabled"] = "is_watermark_enabled";
30
- FeatureGates$1["IsInferenceRegion0"] = "is_inference_region_0";
31
- FeatureGates$1["IsGraphQLUIConfigsEnabled"] = "is_graphql_ui_configs_enabled";
32
- FeatureGates$1["IsGraphQLPageConfigsEnabled"] = "is_graphql_page_configs_enabled";
33
- FeatureGates$1["IsGraphQLComponentConfigsEnabled"] = "is_graphql_component_configs_enabled";
34
- FeatureGates$1["IsChatVariantEnabled"] = "is_chat_variant_enabled";
35
- FeatureGates$1["IsChatVariantAEnabled"] = "is_chat_variant_a_enabled";
36
- FeatureGates$1["IsChatVariantBEnabled"] = "is_chat_variant_b_enabled";
37
- FeatureGates$1["IsUserQueryAlwaysEnabled"] = "is_user_query_always_enabled";
38
- return FeatureGates$1;
39
- }({});
40
-
41
- //#endregion
42
- //#region src/application/models/chatElementDisplayLocation.ts
43
- let ChatElementDisplayLocation = /* @__PURE__ */ function(ChatElementDisplayLocation$1) {
44
- ChatElementDisplayLocation$1["IN_CHAT"] = "in_chat";
45
- ChatElementDisplayLocation$1["CHAT_PREVIEW"] = "chat_preview";
46
- ChatElementDisplayLocation$1["FLOATING_BUTTON"] = "floating_button";
47
- ChatElementDisplayLocation$1["HELP_ME_CHOOSE"] = "help_me_choose";
48
- ChatElementDisplayLocation$1["PLP_IMAGE_BANNER"] = "plp_image_banner";
49
- ChatElementDisplayLocation$1["TOP_REVIEWS_SNIPPET"] = "top_reviews_snippet";
50
- ChatElementDisplayLocation$1["BOTTOM_REVIEWS_SNIPPET"] = "bottom_reviews_snippet";
51
- ChatElementDisplayLocation$1["BLOCK_BACK_BUTTON"] = "block_back_button";
52
- ChatElementDisplayLocation$1["SWITCH_TO_AGENT"] = "switch_to_agent";
53
- ChatElementDisplayLocation$1["CONVERSATIONAL_SEARCH"] = "conversational_search";
54
- ChatElementDisplayLocation$1["GLOBAL_SEARCH_ENTRYPOINT"] = "global_search_entrypoint";
55
- ChatElementDisplayLocation$1["SEARCH_NAV_ENTRYPOINT"] = "search_nav_entrypoint";
56
- ChatElementDisplayLocation$1["SEARCH_PROMPT"] = "search_prompt";
57
- ChatElementDisplayLocation$1["SEARCH_PROMPT_BUTTON"] = "search_prompt_button";
58
- ChatElementDisplayLocation$1["PRODUCT_GRID"] = "product_grid";
59
- ChatElementDisplayLocation$1["UNSPECIFIED"] = "unspecified";
60
- ChatElementDisplayLocation$1["FILTER_MODAL"] = "filter_modal";
61
- ChatElementDisplayLocation$1["PROMPT_CARD"] = "prompt_card";
62
- ChatElementDisplayLocation$1["WINDOW_API_CALL"] = "window_api_call";
63
- return ChatElementDisplayLocation$1;
64
- }({});
65
-
66
- //#endregion
67
- //#region src/application/models/domMutationContinuation.ts
68
- var DomMutationObserverContinuation = /* @__PURE__ */ function(DomMutationObserverContinuation$1) {
69
- DomMutationObserverContinuation$1["CONTINUE"] = "CONTINUE";
70
- DomMutationObserverContinuation$1["EXECUTING"] = "EXECUTING";
71
- DomMutationObserverContinuation$1["STOP"] = "STOP";
72
- return DomMutationObserverContinuation$1;
73
- }(DomMutationObserverContinuation || {});
74
-
75
- //#endregion
76
- //#region src/application/models/domObservationStrategy.ts
77
- var DomObservationStrategy = /* @__PURE__ */ function(DomObservationStrategy$1) {
78
- DomObservationStrategy$1["MutationObserver"] = "MutationObserver";
79
- DomObservationStrategy$1["Polling"] = "Polling";
80
- DomObservationStrategy$1["None"] = "None";
81
- return DomObservationStrategy$1;
82
- }(DomObservationStrategy || {});
83
-
84
- //#endregion
85
- //#region src/application/models/events.ts
86
- let SpiffyEventName = /* @__PURE__ */ function(SpiffyEventName$1) {
87
- SpiffyEventName$1["WidgetOpen"] = "spiffy:widgetopen";
88
- SpiffyEventName$1["WidgetClose"] = "spiffy:widgetclose";
89
- return SpiffyEventName$1;
90
- }({});
91
-
92
- //#endregion
93
- //#region src/application/models/googleAnalyticsEvents.ts
94
- var GoogleAnalyticsEvents = /* @__PURE__ */ function(GoogleAnalyticsEvents$1) {
95
- GoogleAnalyticsEvents$1["ADD_TO_CART_v1"] = "add_to_cart";
96
- GoogleAnalyticsEvents$1["ADD_TO_CART_v2"] = "addToCart";
97
- return GoogleAnalyticsEvents$1;
98
- }(GoogleAnalyticsEvents || {});
99
-
100
- //#endregion
101
- //#region src/application/models/message.ts
102
- let MessageRole = /* @__PURE__ */ function(MessageRole$1) {
103
- MessageRole$1["User"] = "user";
104
- MessageRole$1["Assistant"] = "assistant";
105
- return MessageRole$1;
106
- }({});
107
- let MessageType = /* @__PURE__ */ function(MessageType$1) {
108
- MessageType$1["Text"] = "text";
109
- MessageType$1["SuggestionClicked"] = "suggestion_clicked";
110
- MessageType$1["Product"] = "product";
111
- MessageType$1["ProductSearch"] = "product_search";
112
- MessageType$1["Review"] = "review";
113
- MessageType$1["QueryTyped"] = "query_typed";
114
- MessageType$1["Separator"] = "separator";
115
- MessageType$1["Page"] = "page";
116
- MessageType$1["Search"] = "search";
117
- MessageType$1["Attachment"] = "attachment";
118
- MessageType$1["CXAgentResponse"] = "cx_agent_response";
119
- MessageType$1["Form"] = "form";
120
- MessageType$1["Order"] = "order";
121
- MessageType$1["ProductSearchFilter"] = "product_search_filter";
122
- return MessageType$1;
123
- }({});
124
-
125
- //#endregion
126
- //#region src/application/models/productExperiment.ts
127
- let ProductExperiment = /* @__PURE__ */ function(ProductExperiment$1) {
128
- ProductExperiment$1["Default"] = "default";
129
- return ProductExperiment$1;
130
- }({});
131
-
132
- //#endregion
133
- //#region src/application/models/spiffyWidgets.ts
134
- /**
135
- * Enum of all widget names. These are widgets that are rendered and integrated into
136
- * a merchant's website.
137
- */
138
- let SpiffyWidgets = /* @__PURE__ */ function(SpiffyWidgets$1) {
139
- SpiffyWidgets$1["ImageBanner"] = "image_banner";
140
- SpiffyWidgets$1["ImagePromptCard"] = "image_prompt_card";
141
- SpiffyWidgets$1["SingleImagePrompt"] = "single_image_prompt";
142
- SpiffyWidgets$1["EmbeddedWidget"] = "embedded_widget";
143
- SpiffyWidgets$1["FloatingButton"] = "floating_button";
144
- SpiffyWidgets$1["SuggestionBar"] = "suggestion_bar";
145
- SpiffyWidgets$1["SearchPrompt"] = "search_prompt";
146
- SpiffyWidgets$1["GlobalSearch"] = "global_search";
147
- SpiffyWidgets$1["SearchResults"] = "search_results";
148
- SpiffyWidgets$1["GlobalSearchEntryPoint"] = "global_search_entry_point";
149
- return SpiffyWidgets$1;
150
- }({});
151
-
152
- //#endregion
153
- //#region src/application/models/graphql/queries/getMerchantOrgIdQuery.ts
154
- const getMerchantOrgIdQuery = `
155
- query {
156
- me {
157
- org {
158
- id
159
- }
160
- }
161
- }
162
- `;
163
-
164
- //#endregion
165
- //#region src/application/models/guards/graphQL/isGraphQLColorsConfig.ts
166
- const REQUIRED_COLOR_FIELDS = [
167
- "accent_primary",
168
- "accent_secondary",
169
- "background_dark",
170
- "background_light",
171
- "background_primary",
172
- "background_saturated",
173
- "background_secondary",
174
- "background_secondary_dark",
175
- "background_tertiary",
176
- "border_dark",
177
- "border_light",
178
- "border_medium",
179
- "border_outline",
180
- "text_accent",
181
- "text_light",
182
- "text_link",
183
- "text_primary",
184
- "text_secondary"
185
- ];
186
- const isGraphQLColorsConfig = (data) => {
187
- if (typeof data !== "object" || data === null) {
188
- logger_default.logError("Invalid graphql response for colors config", void 0, { data });
189
- return false;
190
- }
191
- const missingFields = REQUIRED_COLOR_FIELDS.filter((field) => !(field in data) || typeof data[field] !== "string");
192
- if (missingFields.length === REQUIRED_COLOR_FIELDS.length) {
193
- logger_default.logError("All color fields are missing or null", void 0);
194
- return false;
195
- }
196
- if (missingFields.length > 0) {
197
- logger_default.logError("Missing or invalid color fields", void 0, {
198
- data,
199
- missingFields
200
- });
201
- return false;
202
- }
203
- return true;
204
- };
205
-
206
- //#endregion
207
- //#region src/application/models/validators/validateGraphQLColorsConfig.ts
208
- const validateGraphQLColorsConfig = (data) => {
209
- if (!isGraphQLColorsConfig(data)) return;
210
- return {
211
- [ColorNames.TextPrimary]: data.text_primary,
212
- [ColorNames.TextSecondary]: data.text_secondary,
213
- [ColorNames.TextAccent]: data.text_accent,
214
- [ColorNames.TextLink]: data.text_link,
215
- [ColorNames.TextLight]: data.text_light,
216
- [ColorNames.BackgroundPrimary]: data.background_primary,
217
- [ColorNames.BackgroundSecondary]: data.background_secondary,
218
- [ColorNames.BackgroundSecondaryDark]: data.background_secondary_dark,
219
- [ColorNames.BackgroundTertiary]: data.background_tertiary,
220
- [ColorNames.BackgroundDark]: data.background_dark,
221
- [ColorNames.BorderLight]: data.border_light,
222
- [ColorNames.BorderMedium]: data.border_medium,
223
- [ColorNames.BorderDark]: data.border_dark,
224
- [ColorNames.BorderOutline]: data.border_outline,
225
- [ColorNames.AccentPrimary]: data.accent_primary,
226
- [ColorNames.AccentSecondary]: data.accent_secondary,
227
- [ColorNames.BackgroundLight]: data.background_light,
228
- [ColorNames.BackgroundSaturated]: data.background_saturated
229
- };
230
- };
231
-
232
- //#endregion
233
- //#region src/application/models/utils/snakeToCamelTransformer.ts
234
- /**
235
- * Generic utility to transform snake_case object keys to camelCase at runtime.
236
- * This is the runtime equivalent of the CamelCasedPropertiesDeep type utility.
237
- */
238
- const PRESERVED_ACRONYMS = [
239
- "PLP",
240
- "PDP",
241
- "SVG"
242
- ];
243
- /**
244
- * Converts a snake_case string to camelCase
245
- * Handles specific acronyms like PLP and PDP correctly
246
- */
247
- const toCamelCase = (str) => {
248
- let processedStr = str;
249
- for (const acronym of PRESERVED_ACRONYMS) {
250
- const regex = new RegExp(`_${acronym}_?`, "gi");
251
- if (processedStr.match(regex)) processedStr = processedStr.replace(regex, (v) => v.endsWith("_") ? `${acronym}_` : `${acronym}`);
252
- }
253
- return processedStr.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
254
- };
255
- /**
256
- * Converts a camelCase string to snake_case
257
- * Handles consecutive capital letters correctly (e.g., "PDP" -> "pdp", not "p_d_p")
258
- * Preserves specific acronyms like PLP and PDP as lowercase in snake_case
259
- */
260
- const toSnakeCase = (str) => str.replace(/([A-Z])(?=[a-z])/g, "_$1").replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase().replace(/^_/, "");
261
- /**
262
- * Recursively transforms all object keys from snake_case to camelCase
263
- */
264
- const transformSnakeToCamel = (obj) => {
265
- if (obj === null || obj === void 0) return obj;
266
- if (Array.isArray(obj)) return obj.map((val) => transformSnakeToCamel(val));
267
- if (typeof obj === "object") {
268
- const result = {};
269
- for (const [key, value] of Object.entries(obj)) {
270
- const camelKey = toCamelCase(key);
271
- result[camelKey] = transformSnakeToCamel(value);
272
- }
273
- return result;
274
- }
275
- return obj;
276
- };
277
- /**
278
- * Recursively transforms all object keys from camelCase to snake_case
279
- */
280
- const transformCamelToSnake = (obj) => {
281
- if (obj === null || obj === void 0) return obj;
282
- if (Array.isArray(obj)) return obj.map(transformCamelToSnake);
283
- if (typeof obj === "object") {
284
- const result = {};
285
- for (const [key, value] of Object.entries(obj)) {
286
- const snakeKey = toSnakeCase(key);
287
- result[snakeKey] = transformCamelToSnake(value);
288
- }
289
- return result;
290
- }
291
- return obj;
292
- };
293
-
294
- //#endregion
295
- //#region src/application/service/domMutations/domInsertionService.ts
296
- var DOMInsertionType = /* @__PURE__ */ function(DOMInsertionType$1) {
297
- DOMInsertionType$1["AFTER"] = "after";
298
- DOMInsertionType$1["BEFORE"] = "before";
299
- DOMInsertionType$1["ADJACENT_AFTER_BEGIN"] = "adjacent-after-begin";
300
- DOMInsertionType$1["ADJACENT_BEFORE_BEGIN"] = "adjacent-before-begin";
301
- DOMInsertionType$1["ADJACENT_AFTER_END"] = "adjacent-after-end";
302
- DOMInsertionType$1["ADJACENT_BEFORE_END"] = "adjacent-before-end";
303
- DOMInsertionType$1["APPEND_CHILD"] = "append-child";
304
- DOMInsertionType$1["NONE"] = "none";
305
- return DOMInsertionType$1;
306
- }(DOMInsertionType || {});
307
- const DOMInsertionTypeToInsertPosition = (type) => {
308
- switch (type) {
309
- case DOMInsertionType.ADJACENT_AFTER_BEGIN: return "afterbegin";
310
- case DOMInsertionType.BEFORE:
311
- case DOMInsertionType.ADJACENT_BEFORE_BEGIN: return "beforebegin";
312
- case DOMInsertionType.ADJACENT_BEFORE_END: return "beforeend";
313
- case DOMInsertionType.AFTER:
314
- case DOMInsertionType.ADJACENT_AFTER_END:
315
- default: return "afterend";
316
- }
317
- };
318
- var DOMInsertionService = class {
319
- static insert(targetElement, nodeToInsert, insertionType) {
320
- switch (insertionType) {
321
- case DOMInsertionType.AFTER:
322
- targetElement.after(nodeToInsert);
323
- break;
324
- case DOMInsertionType.BEFORE:
325
- targetElement.before(nodeToInsert);
326
- break;
327
- case DOMInsertionType.ADJACENT_AFTER_BEGIN:
328
- targetElement.insertAdjacentElement("afterbegin", nodeToInsert);
329
- break;
330
- case DOMInsertionType.ADJACENT_BEFORE_BEGIN:
331
- targetElement.insertAdjacentElement("beforebegin", nodeToInsert);
332
- break;
333
- case DOMInsertionType.ADJACENT_AFTER_END:
334
- targetElement.insertAdjacentElement("afterend", nodeToInsert);
335
- break;
336
- case DOMInsertionType.ADJACENT_BEFORE_END:
337
- targetElement.insertAdjacentElement("beforeend", nodeToInsert);
338
- break;
339
- case DOMInsertionType.APPEND_CHILD:
340
- targetElement.appendChild(nodeToInsert);
341
- break;
342
- case DOMInsertionType.NONE: break;
343
- default: throw new Error(`Invalid insertion type: ${insertionType}`);
344
- }
345
- }
346
- /**
347
- * Get the insertion point for the widget.
348
- * @param selector - The selector to find the insertion point.
349
- * @param selectionIndex - For multiple matches, pick the nth element. Can be negative to insert from the end (-1 is the last element). (optional, default first)
350
- * @returns The insertion point element or null if not found.
351
- */
352
- static getInsertionPoint(selector, selectionIndex) {
353
- let elem = null;
354
- if (selectionIndex === void 0 || selectionIndex === 0) {
355
- elem = document.querySelector(selector);
356
- if (elem?.parentElement) return elem;
357
- } else {
358
- const elems = document.querySelectorAll(selector);
359
- const minLength = selectionIndex > 0 ? selectionIndex + 1 : -selectionIndex;
360
- const index = selectionIndex > 0 ? selectionIndex : elems.length + selectionIndex;
361
- if (elems.length >= minLength && elems[index].parentElement) return elems[index];
362
- }
363
- return null;
364
- }
365
- };
366
-
367
- //#endregion
368
- //#region src/application/service/domMutations/GridInsertionService.ts
369
- var GridInsertionType = /* @__PURE__ */ function(GridInsertionType$1) {
370
- GridInsertionType$1["FIXED_1"] = "fixed-1";
371
- GridInsertionType$1["FIXED_2"] = "fixed-2";
372
- GridInsertionType$1["FIXED_3"] = "fixed-3";
373
- GridInsertionType$1["FIXED_4"] = "fixed-4";
374
- GridInsertionType$1["FIXED_5"] = "fixed-5";
375
- GridInsertionType$1["FIXED_6"] = "fixed-6";
376
- GridInsertionType$1["FIXED_7"] = "fixed-7";
377
- GridInsertionType$1["FIXED_8"] = "fixed-8";
378
- GridInsertionType$1["FIXED_9"] = "fixed-9";
379
- GridInsertionType$1["FIXED_12"] = "fixed-12";
380
- GridInsertionType$1["FIXED_13"] = "fixed-13";
381
- GridInsertionType$1["ROW_1"] = "row-1";
382
- GridInsertionType$1["ROW_2"] = "row-2";
383
- GridInsertionType$1["ROW_3"] = "row-3";
384
- GridInsertionType$1["ROW_4"] = "row-4";
385
- return GridInsertionType$1;
386
- }(GridInsertionType || {});
387
- var GridInsertionService = class GridInsertionService {
388
- static insert(gridInsertionType, targetElement, nodeToInsert, insertionType) {
389
- switch (gridInsertionType) {
390
- case GridInsertionType.FIXED_1:
391
- GridInsertionService.fixedInsert(targetElement, 1, nodeToInsert, insertionType);
392
- break;
393
- case GridInsertionType.FIXED_2:
394
- GridInsertionService.fixedInsert(targetElement, 2, nodeToInsert, insertionType);
395
- break;
396
- case GridInsertionType.FIXED_3:
397
- GridInsertionService.fixedInsert(targetElement, 3, nodeToInsert, insertionType);
398
- break;
399
- case GridInsertionType.FIXED_4:
400
- GridInsertionService.fixedInsert(targetElement, 4, nodeToInsert, insertionType);
401
- break;
402
- case GridInsertionType.FIXED_5:
403
- GridInsertionService.fixedInsert(targetElement, 5, nodeToInsert, insertionType);
404
- break;
405
- case GridInsertionType.FIXED_6:
406
- GridInsertionService.fixedInsert(targetElement, 6, nodeToInsert, insertionType);
407
- break;
408
- case GridInsertionType.FIXED_7:
409
- GridInsertionService.fixedInsert(targetElement, 7, nodeToInsert, insertionType);
410
- break;
411
- case GridInsertionType.FIXED_8:
412
- GridInsertionService.fixedInsert(targetElement, 8, nodeToInsert, insertionType);
413
- break;
414
- case GridInsertionType.FIXED_9:
415
- GridInsertionService.fixedInsert(targetElement, 9, nodeToInsert, insertionType);
416
- break;
417
- case GridInsertionType.FIXED_12:
418
- GridInsertionService.fixedInsert(targetElement, 12, nodeToInsert, insertionType);
419
- break;
420
- case GridInsertionType.FIXED_13:
421
- GridInsertionService.fixedInsert(targetElement, 13, nodeToInsert, insertionType);
422
- break;
423
- case GridInsertionType.ROW_1:
424
- GridInsertionService.rowInsert(targetElement, nodeToInsert, 1);
425
- break;
426
- case GridInsertionType.ROW_2:
427
- GridInsertionService.rowInsert(targetElement, nodeToInsert, 2);
428
- break;
429
- case GridInsertionType.ROW_3:
430
- GridInsertionService.rowInsert(targetElement, nodeToInsert, 3);
431
- break;
432
- case GridInsertionType.ROW_4:
433
- GridInsertionService.rowInsert(targetElement, nodeToInsert, 4);
434
- break;
435
- default: logger_default.logError(`Skipping grid insertion: invalid grid insertion type "${gridInsertionType}". \
436
- Valid types are: ${Object.keys(GridInsertionType).join(", ")}`, void 0);
437
- }
438
- }
439
- /**
440
- * Inserts a node into a grid row at the specified index starting from index 1. If the index
441
- * is higher than the total number of rows, the node will be inserted at the end of the grid.
442
- * This function does not make any assumptions about the column span of the inserted node - that
443
- * should be handled by the orgConfig instead.
444
- *
445
- * @param targetElement - The target element to insert the node into.
446
- * @param nodeToInsert - The node to insert into the grid.
447
- * @param rowIndex - The index of the row to insert the node into.
448
- */
449
- static rowInsert(targetElement, nodeToInsert, rowIndex) {
450
- const node = nodeToInsert;
451
- node.style.gridRow = rowIndex.toString();
452
- node.style.gridColumn = "1/-1";
453
- DOMInsertionService.insert(targetElement, node, DOMInsertionType.APPEND_CHILD);
454
- }
455
- static fixedInsert(targetElement, insertionGridIndex, nodeToInsert, insertionType) {
456
- const childCount = targetElement.children.length;
457
- const actualIndex = Math.min(insertionGridIndex - 1, childCount - 1);
458
- const targetChild = targetElement.children[actualIndex];
459
- if (!targetChild) {
460
- logger_default.logWarn("Skipping grid insertion: grid has no elements", void 0);
461
- return;
462
- }
463
- DOMInsertionService.insert(targetChild, nodeToInsert, insertionType);
464
- }
465
- };
466
-
467
- //#endregion
468
- //#region src/application/models/validators/validateGraphQLFrontendConfig.ts
469
- const validateAndTransformPageVariants = (config) => {
470
- const { variantChecks, widgetMounting,...rest } = transformSnakeToCamel(config);
471
- const variantTests = Array.isArray(variantChecks) ? variantChecks.map(({ checkType,...restCheck }) => ({
472
- ...restCheck,
473
- testType: checkType
474
- })) : [];
475
- const normalizedWidgetMounting = Array.isArray(widgetMounting) ? widgetMounting.map(({ mountingPointWidgets,...restMounting }) => ({
476
- ...restMounting,
477
- ...Array.isArray(mountingPointWidgets) ? { mountingPointWidgets: mountingPointWidgets.map(({ checks,...restWidget }) => ({
478
- ...restWidget,
479
- tests: Array.isArray(checks) ? checks.map(({ checkType,...restCheck }) => ({
480
- ...restCheck,
481
- testType: checkType
482
- })) : []
483
- })) } : {}
484
- })) : [];
485
- const normalizedConfig = {
486
- ...rest,
487
- ...variantTests ? { variantTests } : {},
488
- ...normalizedWidgetMounting ? { widgetMounting: normalizedWidgetMounting } : {}
489
- };
490
- const variantId = normalizedConfig.variantId;
491
- const variantType = normalizedConfig.variantType;
492
- if (typeof variantId !== "string" || !variantId) throw new Error(`Missing or invalid variantId for pageVariant`);
493
- if (typeof variantType !== "string" || !variantType) throw new Error(`Missing or invalid variantType for pageVariant '${variantId}'`);
494
- if (!Array.isArray(variantTests)) throw new Error(`Missing or invalid variantTests for pageVariant '${variantId}'. Must be an array`);
495
- for (const test of variantTests) {
496
- if (!test.testType || typeof test.testType !== "string") throw new Error(`Invalid variantTest.testType for pageVariant '${variantId}'`);
497
- if (!Object.values(PageVariantTestType).includes(test.testType)) throw new Error(`Invalid testType '${test.testType}' for pageVariant '${variantId}'. Valid types: ${Object.values(PageVariantTestType).join(", ")}`);
498
- }
499
- if (!Array.isArray(normalizedWidgetMounting)) throw new Error(`Missing or invalid widgetMounting for pageVariant '${variantId}'. Must be an array`);
500
- for (const mounting of normalizedWidgetMounting) {
501
- if (typeof mounting.mountingConfigId !== "string" || !mounting.mountingConfigId) throw new Error(`Invalid mountingConfigId in widgetMounting for pageVariant '${variantId}'`);
502
- if (mounting.widgetConfigId && typeof mounting.widgetConfigId !== "string") throw new Error(`Invalid widgetConfigId in widgetMounting for pageVariant '${variantId}'`);
503
- if (mounting.mountingPointWidgets) for (const widget of mounting.mountingPointWidgets) {
504
- if (typeof widget.widgetConfigId !== "string" || !widget.widgetConfigId) throw new Error(`Invalid widgetConfigId in mountingPointWidgets for pageVariant '${variantId}'`);
505
- if (!Array.isArray(widget.tests)) throw new Error(`Invalid or missing tests in mountingPointWidgets for pageVariant '${variantId}'`);
506
- }
507
- }
508
- if (variantType === "plp") {
509
- if (typeof normalizedConfig.plpIdExtractor !== "string" || !normalizedConfig.plpIdExtractor) throw new Error(`Missing or invalid plpIdExtractor for PLP pageVariant '${variantId}'`);
510
- }
511
- if (variantType === "pdp") {
512
- if (typeof normalizedConfig.productIdExtractor !== "string" || !normalizedConfig.productIdExtractor) throw new Error(`Missing or invalid productIdExtractor for PDP pageVariant '${variantId}'`);
513
- if (normalizedConfig.parentProductIdExtractor && typeof normalizedConfig.parentProductIdExtractor !== "string") throw new Error(`Invalid parentProductIdExtractor for PDP pageVariant '${variantId}'. Must be string if provided`);
514
- }
515
- return normalizedConfig;
516
- };
517
- const validateAndTransformMountingConfig = (config, configKey) => {
518
- const normalizedConfig = { ...config };
519
- if (normalizedConfig.checkId && !normalizedConfig.testId) {
520
- normalizedConfig.testId = normalizedConfig.checkId;
521
- delete normalizedConfig.checkId;
522
- }
523
- if (typeof normalizedConfig.mountingConfigId !== "string" || !normalizedConfig.mountingConfigId) throw new Error(`Missing or invalid mountingConfigId for config '${configKey}'`);
524
- if (typeof normalizedConfig.containerId !== "string" || !normalizedConfig.containerId) throw new Error(`Missing or invalid containerId for config '${configKey}'`);
525
- if (typeof normalizedConfig.testId !== "string" || !normalizedConfig.testId) throw new Error(`Missing or invalid testId for config '${configKey}'`);
526
- if (!normalizedConfig.insertionPoint || typeof normalizedConfig.insertionPoint !== "object" || Array.isArray(normalizedConfig.insertionPoint)) throw new Error(`Missing or invalid insertionPoint for config '${configKey}'`);
527
- const insertionPoint = normalizedConfig.insertionPoint;
528
- if (typeof insertionPoint.selector !== "string" || !insertionPoint.selector) throw new Error(`Missing or invalid insertionPoint.selector for config '${configKey}'`);
529
- if (typeof insertionPoint.insertionType !== "string" || !insertionPoint.insertionType) throw new Error(`Missing or invalid insertionPoint.insertionType for config '${configKey}'`);
530
- if (!Object.values(DOMInsertionType).includes(insertionPoint.insertionType)) throw new Error(`Invalid insertionPoint.insertionType '${insertionPoint.insertionType}' for config '${configKey}'. Valid types: ${Object.values(DOMInsertionType).join(", ")}`);
531
- if (insertionPoint.selectionIndex != null && typeof insertionPoint.selectionIndex !== "number") throw new Error(`Invalid insertionPoint.selectionIndex for config '${configKey}'. Must be a number or null/undefined`);
532
- let parentInsertionPoint;
533
- if (normalizedConfig.parentInsertionPoint) {
534
- if (typeof normalizedConfig.parentInsertionPoint !== "object" || Array.isArray(normalizedConfig.parentInsertionPoint)) throw new Error(`Invalid parentInsertionPoint for config '${configKey}'. Must be an object`);
535
- const parentPoint = normalizedConfig.parentInsertionPoint;
536
- if (typeof parentPoint.selector !== "string" || !parentPoint.selector) throw new Error(`Missing or invalid parentInsertionPoint.selector for config '${configKey}'`);
537
- if (typeof parentPoint.insertionType !== "string" || !parentPoint.insertionType) throw new Error(`Missing or invalid parentInsertionPoint.insertionType for config '${configKey}'`);
538
- if (!Object.values(DOMInsertionType).includes(parentPoint.insertionType)) throw new Error(`Invalid parentInsertionPoint.insertionType '${parentPoint.insertionType}' for config '${configKey}'. Valid types: ${Object.values(DOMInsertionType).join(", ")}`);
539
- if (parentPoint.selectionIndex != null && typeof parentPoint.selectionIndex !== "number") throw new Error(`Invalid parentInsertionPoint.selectionIndex for config '${configKey}'. Must be a number or null/undefined`);
540
- parentInsertionPoint = {
541
- selector: parentPoint.selector,
542
- insertionType: parentPoint.insertionType,
543
- selectionIndex: parentPoint.selectionIndex
544
- };
545
- }
546
- let wrappingElement;
547
- if (normalizedConfig.wrappingElement) {
548
- if (typeof normalizedConfig.wrappingElement !== "object" || Array.isArray(normalizedConfig.wrappingElement)) throw new Error(`Invalid wrappingElement for config '${configKey}'. Must be an object`);
549
- const wrapping = normalizedConfig.wrappingElement;
550
- if (typeof wrapping.className !== "string" || !wrapping.className) throw new Error(`Missing or invalid wrappingElement.className for config '${configKey}'`);
551
- if (typeof wrapping.element !== "string" || !wrapping.element) throw new Error(`Missing or invalid wrappingElement.element for config '${configKey}'`);
552
- if (typeof wrapping.insertionType !== "string" || !wrapping.insertionType) throw new Error(`Missing or invalid wrappingElement.insertionType for config '${configKey}'`);
553
- if (!Object.values(DOMInsertionType).includes(wrapping.insertionType)) throw new Error(`Invalid wrappingElement.insertionType '${wrapping.insertionType}' for config '${configKey}'. Valid types: ${Object.values(DOMInsertionType).join(", ")}`);
554
- wrappingElement = {
555
- className: wrapping.className,
556
- element: wrapping.element,
557
- insertionType: wrapping.insertionType
558
- };
559
- }
560
- if (normalizedConfig.divCheckSelector != null && typeof normalizedConfig.divCheckSelector !== "string") throw new Error(`Invalid divCheckSelector for config '${configKey}'. Must be a string or null/undefined`);
561
- if (normalizedConfig.className != null && typeof normalizedConfig.className !== "string") throw new Error(`Invalid className for config '${configKey}'. Must be a string or null/undefined`);
562
- if (normalizedConfig.suppressionSelector != null && typeof normalizedConfig.suppressionSelector !== "string") throw new Error(`Invalid suppressionSelector for config '${configKey}'. Must be a string or null/undefined`);
563
- if (normalizedConfig.dataAttributes != null && (typeof normalizedConfig.dataAttributes !== "object" || Array.isArray(normalizedConfig.dataAttributes))) throw new Error(`Invalid dataAttributes for config '${configKey}'. Must be an object or null/undefined`);
564
- if (normalizedConfig.style != null && (typeof normalizedConfig.style !== "object" || Array.isArray(normalizedConfig.style))) throw new Error(`Invalid style for config '${configKey}'. Must be an object or null/undefined`);
565
- let gridInsertionType;
566
- if (normalizedConfig.gridInsertionType) {
567
- if (typeof normalizedConfig.gridInsertionType !== "string" || !normalizedConfig.gridInsertionType) throw new Error(`Invalid gridInsertionType for config '${configKey}'. Must be a string`);
568
- if (!Object.values(GridInsertionType).includes(normalizedConfig.gridInsertionType)) throw new Error(`Invalid gridInsertionType '${normalizedConfig.gridInsertionType}' for config '${configKey}'. Valid types: ${Object.values(GridInsertionType).join(", ")}`);
569
- gridInsertionType = normalizedConfig.gridInsertionType;
570
- }
571
- const result = {
572
- mountingConfigId: normalizedConfig.mountingConfigId,
573
- containerId: normalizedConfig.containerId,
574
- testId: normalizedConfig.testId,
575
- insertionPoint: {
576
- selector: insertionPoint.selector,
577
- insertionType: insertionPoint.insertionType,
578
- ...insertionPoint.selectionIndex != null && { selectionIndex: insertionPoint.selectionIndex }
579
- }
580
- };
581
- if (parentInsertionPoint) result.parentInsertionPoint = parentInsertionPoint;
582
- if (gridInsertionType) result.gridInsertionType = gridInsertionType;
583
- if (wrappingElement) result.wrappingElement = wrappingElement;
584
- if (normalizedConfig.divCheckSelector) result.divCheckSelector = normalizedConfig.divCheckSelector;
585
- if (normalizedConfig.className) result.className = normalizedConfig.className;
586
- if (normalizedConfig.suppressionSelector) result.suppressionSelector = normalizedConfig.suppressionSelector;
587
- if (normalizedConfig.dataAttributes) result.dataAttributes = normalizedConfig.dataAttributes;
588
- if (normalizedConfig.style) result.style = normalizedConfig.style;
589
- return result;
590
- };
591
- const validateAndTransformWidgetConfig = (config, configKey) => {
592
- const normalizedConfig = transformSnakeToCamel(config);
593
- if (typeof normalizedConfig.widgetConfigId !== "string" || !normalizedConfig.widgetConfigId) throw new Error(`Missing or invalid widgetConfigId for widget config '${configKey}'`);
594
- if (typeof normalizedConfig.type !== "string" || !normalizedConfig.type) throw new Error(`Missing or invalid type for widget config '${configKey}'`);
595
- if (normalizedConfig.contentId != null && typeof normalizedConfig.contentId !== "string") throw new Error(`Invalid contentId for widget config '${configKey}'. Must be a string or null/undefined`);
596
- return normalizedConfig;
597
- };
598
- const validateGraphQLFrontendConfig = (data) => {
599
- if (data === null || data === void 0) return;
600
- if (typeof data !== "object" || Array.isArray(data)) {
601
- logger_default.logWarn("Invalid GraphQL frontend config data: not an object", void 0, { data });
602
- return;
603
- }
604
- const obj = data;
605
- if ("merchant_override_css" in obj && typeof obj.merchant_override_css !== "string" && obj.merchant_override_css !== null) {
606
- logger_default.logWarn("Invalid GraphQL frontend config data: merchant_override_css must be a string or null", void 0, { data });
607
- return;
608
- }
609
- if ("page_variants" in obj) {
610
- if (obj.page_variants !== void 0 && obj.page_variants !== null && !Array.isArray(obj.page_variants)) {
611
- logger_default.logWarn("Invalid GraphQL frontend config data: page_variants must be an array or null/undefined", void 0, { data });
612
- return;
613
- }
614
- }
615
- if ("mounting_configs" in obj) {
616
- if (obj.mounting_configs !== void 0 && obj.mounting_configs !== null && !Array.isArray(obj.mounting_configs)) {
617
- logger_default.logWarn("Invalid GraphQL frontend config data: mounting_configs must be an array or null/undefined", void 0, { data });
618
- return;
619
- }
620
- }
621
- if ("widget_configs" in obj) {
622
- if (obj.widget_configs !== void 0 && obj.widget_configs !== null && !Array.isArray(obj.widget_configs)) {
623
- logger_default.logWarn("Invalid GraphQL frontend config data: widget_configs must be an array or null/undefined", void 0, { data });
624
- return;
625
- }
626
- }
627
- if ("ui_configs" in obj && typeof obj.ui_configs !== "object" && obj.ui_configs !== null) {
628
- logger_default.logWarn("Invalid GraphQL frontend config data: ui_configs must be an object or null/undefined", void 0, { data });
629
- return;
630
- }
631
- try {
632
- const transformedData = transformSnakeToCamel(obj);
633
- if (transformedData.pageVariants && Array.isArray(transformedData.pageVariants)) {
634
- const pageVariantsArray = transformedData.pageVariants;
635
- const validatedPageVariants = [];
636
- for (const variant of pageVariantsArray) if (variant && typeof variant === "object" && typeof variant.variantId === "string") try {
637
- const validatedVariant = validateAndTransformPageVariants(variant);
638
- validatedPageVariants.push(validatedVariant);
639
- } catch (error) {
640
- logger_default.logWarn("Invalid page variant, skipping", error, {
641
- variantId: variant.variantId,
642
- variant
643
- });
644
- }
645
- else logger_default.logWarn("Invalid page variant structure, skipping", void 0, { variant });
646
- transformedData.pageVariants = validatedPageVariants;
647
- }
648
- if (transformedData.mountingConfigs && Array.isArray(transformedData.mountingConfigs)) {
649
- const mountingConfigsArray = transformedData.mountingConfigs;
650
- const mountingConfigsRecord = {};
651
- for (const item of mountingConfigsArray) if (item && typeof item.key === "string" && item.config && typeof item.config === "object") try {
652
- const config = item.config;
653
- const validatedConfig = validateAndTransformMountingConfig(config, item.key);
654
- mountingConfigsRecord[item.key] = validatedConfig;
655
- } catch (error) {
656
- logger_default.logWarn("Invalid mounting config, skipping", error, {
657
- configKey: item.key,
658
- config: item.config
659
- });
660
- }
661
- else logger_default.logWarn("Invalid mounting config item structure, skipping", void 0, { item });
662
- transformedData.mountingConfigs = mountingConfigsRecord;
663
- }
664
- if (transformedData.widgetConfigs && Array.isArray(transformedData.widgetConfigs)) {
665
- const widgetConfigsArray = transformedData.widgetConfigs;
666
- const widgetConfigsRecord = {};
667
- for (const item of widgetConfigsArray) if (item && typeof item.key === "string" && item.config && typeof item.config === "object") try {
668
- const config = item.config;
669
- const validatedConfig = validateAndTransformWidgetConfig(config, item.key);
670
- widgetConfigsRecord[item.key] = validatedConfig;
671
- } catch (error) {
672
- logger_default.logWarn("Invalid widget config, skipping", error, {
673
- configKey: item.key,
674
- config: item.config
675
- });
676
- }
677
- else logger_default.logWarn("Invalid widget config item structure, skipping", void 0, { item });
678
- transformedData.widgetConfigs = widgetConfigsRecord;
679
- }
680
- return transformedData;
681
- } catch (error) {
682
- logger_default.logWarn("Failed to validate and transform GraphQL frontend config data", error, { data });
683
- return;
684
- }
685
- };
686
-
687
- //#endregion
688
- //#region src/application/models/validators/validateGraphQLOrgId.ts
689
- const validateGraphQLOrgId = (data) => {
690
- if (typeof data !== "string" || data === "") return;
691
- return data;
692
- };
693
-
694
- //#endregion
695
- //#region src/application/service/localStorageService.ts
696
- let LocalStorageKeys = /* @__PURE__ */ function(LocalStorageKeys$1) {
697
- LocalStorageKeys$1["ChatId"] = "v1-spiffy-chat-session-id";
698
- LocalStorageKeys$1["SpiffyOnOverride"] = "spiffy_on";
699
- LocalStorageKeys$1["EnviveOnOverride"] = "envive_on";
700
- return LocalStorageKeys$1;
701
- }({});
702
- var LocalStorageService = class {
703
- static setItem(key, value) {
704
- localStorage.setItem(key, value);
705
- window.dispatchEvent(new StorageEvent("storage", {
706
- key,
707
- newValue: value
708
- }));
709
- }
710
- static getItem(key) {
711
- return localStorage.getItem(key);
712
- }
713
- static setSpiffyOnFeatureFlag(value) {
714
- if (value === true) localStorage.setItem(LocalStorageKeys.SpiffyOnOverride, "true");
715
- else if (value === false) localStorage.setItem(LocalStorageKeys.SpiffyOnOverride, "false");
716
- }
717
- static getSpiffyOnFeatureFlag() {
718
- return localStorage.getItem(LocalStorageKeys.SpiffyOnOverride);
719
- }
720
- static getLocalStorage() {
721
- const ls = window?.localStorage;
722
- if (!ls) logger_default.logError("localStorage is not available", void 0);
723
- return ls;
724
- }
725
- static {
726
- this.listenersCache = {};
727
- }
728
- static listenerForKey(listener) {
729
- if (!this.listenersCache[listener.storageKey]) this.listenersCache[listener.storageKey] = (event) => {
730
- if (event.key !== listener.storageKey) return;
731
- logger_default.logDebug(`[spiffy-ai] Storage event key=${event.key}, value=`, event.newValue);
732
- listener.listener(event);
733
- };
734
- return this.listenersCache[listener.storageKey];
735
- }
736
- /**
737
- * Attach a listener to the window's storage event. Safe to call multiple times.
738
- * @param listener
739
- */
740
- static attachListener(listener) {
741
- window.addEventListener("storage", this.listenerForKey(listener));
742
- }
743
- static detachListener(listener) {
744
- window.removeEventListener("storage", this.listenerForKey(listener));
745
- }
746
- };
747
-
748
- //#endregion
749
- //#region src/application/service/environmentService.ts
750
- var EnvironmentService = class {
751
- static getApiEndpoint() {
752
- const { baseUrl } = useEnviveConfig();
753
- return baseUrl || "https://commerce-api.dev.spiffy.ai";
754
- }
755
- static getContextSource() {
756
- if (window.IS_STORYBOOK) return ContextSourceEnum.Test;
757
- const { contextSource } = useEnviveConfig();
758
- if (contextSource) return contextSource;
759
- if (LocalStorageService.getSpiffyOnFeatureFlag() === "true") return ContextSourceEnum.Playground;
760
- return ContextSourceEnum.App;
761
- }
762
- static getIdentifyingPrefix() {
763
- return "spiffy";
764
- }
765
- static {
766
- this.getEnvironment = () => {
767
- const { env } = useEnviveConfig();
768
- if (!env) return "dev";
769
- switch (env.toLowerCase()) {
770
- case "production":
771
- case "prod": return "prod";
772
- default: return "dev";
773
- }
774
- };
775
- }
776
- };
777
-
778
- //#endregion
779
- //#region src/application/utils/urlsParser.ts
780
- const parseHref = (href) => {
781
- try {
782
- const url = new URL(href);
783
- const urlSearchParams = new URLSearchParams(url.search);
784
- return {
785
- url,
786
- urlSearchParams
787
- };
788
- } catch (e) {
789
- return {
790
- url: void 0,
791
- urlSearchParams: void 0
792
- };
793
- }
794
- };
795
- const createUrlWithQueryParams = (url, queryParams) => {
796
- const urlObj = new URL(url, window.location.href);
797
- Object.entries(queryParams).forEach(([value, key]) => urlObj.searchParams.append(value, key));
798
- return urlObj.href;
799
- };
800
- const getQueryParam = (key) => {
801
- return new URL(window.location.href).searchParams.get(key);
802
- };
803
- const buildSearchHash = (message) => `#evs=true&s=${message.id}&q=${message.metadata.generatedQuery}`;
804
- const buildSearchStartHash = (query) => `#evs=true&q=${query}`;
805
- const parseSearchHash = (hash) => {
806
- if (!hash.startsWith("#evs=true")) return {
807
- id: null,
808
- query: null
809
- };
810
- const params = Object.fromEntries(hash.split("&").map((param) => param.split("=")));
811
- return {
812
- id: params.s ? decodeURIComponent(params.s) : null,
813
- query: params.q ? decodeURIComponent(params.q) : null
814
- };
815
- };
816
- window.history.pushState(null, "");
817
-
818
- //#endregion
819
- //#region src/application/models/validators/validateSuggestion.ts
820
- const validateSuggestion = (data) => {
821
- if (!isSuggestion(data)) return;
822
- return {
823
- id: data.id,
824
- category: data.category,
825
- content: data.content,
826
- createdAt: data.created_at,
827
- isAnswer: data.is_answer
828
- };
829
- };
830
-
831
- //#endregion
832
- //#region src/application/models/guards/api/isApiPLPEventAttributes.ts
833
- const isApiPLPIdAttribute = (data) => {
834
- if (data == null || typeof data !== "object") return false;
835
- if (!("id" in data) || typeof data.id !== "string") return false;
836
- return true;
837
- };
838
- const isApiPLPEventAttributes = (data) => {
839
- if (data == null || typeof data !== "object") return false;
840
- if (!("category" in data) || typeof data.category !== "string" || !Object.values(PLPAttributeCategory).includes(data.category)) return false;
841
- if (!("attributes" in data) || typeof data.attributes !== "object" || !isApiPLPIdAttribute(data.attributes)) return false;
842
- return true;
843
- };
844
-
845
- //#endregion
846
- //#region src/application/models/guards/api/isApiFormSubmittedResponseAttributes.ts
847
- const isApiFormSubmittedResponseAttributes = (data) => {
848
- if (data == null || typeof data !== "object") {
849
- logger_default.logError("isApiFormSubmittedResponseAttributes", "data is null or not an object", data);
850
- return false;
851
- }
852
- if (!hasPropertyOfType(data, "filled_schema", "object")) {
853
- logger_default.logError("isApiFormSubmittedResponseAttributes", "filled_schema is not an object", data);
854
- return false;
855
- }
856
- if (!hasPropertyOfType(data, "form_response_id", "string")) {
857
- logger_default.logError("isApiFormSubmittedResponseAttributes", "form_response_id is not a string", data);
858
- return false;
859
- }
860
- if (!("form_type" in data) || !Object.values(FormType).includes(data.form_type)) {
861
- logger_default.logError("isApiFormSubmittedResponseAttributes", "form_type is not a valid form type enum", data);
862
- return false;
863
- }
864
- return true;
865
- };
866
-
867
- //#endregion
868
- //#region src/application/models/validators/validateUserEvent.ts
869
- const validateUserEvent = (data) => {
870
- if (!isApiUserEvent(data)) return;
871
- if (data.category === UserEventCategory$1.PdpVisit && isApiPDPAttributes(data.attributes)) return {
872
- eventId: data.event_id,
873
- createdAt: data.created_at,
874
- category: UserEventCategory$1.PdpVisit,
875
- attributes: {
876
- productId: data.attributes.product_id,
877
- parentProductId: data.attributes.parent_product_id,
878
- url: data.attributes.url
879
- }
880
- };
881
- if (data.category === UserEventCategory$1.QueryTyped && isApiQueryTypedAttributes(data.attributes)) return {
882
- eventId: data.event_id,
883
- createdAt: data.created_at,
884
- category: UserEventCategory$1.QueryTyped,
885
- attributes: { query: data.attributes.query }
886
- };
887
- if (data.category === UserEventCategory$1.Search && isApiSearchAttributes(data.attributes)) return {
888
- eventId: data.event_id,
889
- createdAt: data.created_at,
890
- category: UserEventCategory$1.Search,
891
- attributes: {
892
- searchTerm: data.attributes.search_term,
893
- selectedFilters: data.attributes.selected_filters
894
- }
895
- };
896
- if (data.category === UserEventCategory$1.SuggestionClicked && isApiSuggestionClickedAttributes(data.attributes)) return {
897
- eventId: data.event_id,
898
- createdAt: data.created_at,
899
- category: UserEventCategory$1.SuggestionClicked,
900
- attributes: { suggestionId: data.attributes.suggestion_id }
901
- };
902
- if (data.category === UserEventCategory$1.PlpVisit && isApiPLPEventAttributes(data.attributes)) {
903
- if (isApiPLPIdAttribute(data.attributes)) return {
904
- eventId: data.event_id,
905
- createdAt: data.created_at,
906
- category: UserEventCategory$1.PlpVisit,
907
- attributes: {
908
- category: data.attributes.category,
909
- attributes: { id: data.attributes.id }
910
- }
911
- };
912
- }
913
- if (data.category === UserEventCategory$1.FormSubmitted && isApiFormSubmittedResponseAttributes(data.attributes)) return {
914
- eventId: data.event_id,
915
- createdAt: data.created_at,
916
- category: UserEventCategory$1.FormSubmitted,
917
- attributes: {
918
- filledSchema: { ...data.attributes.filled_schema },
919
- formResponseId: data.attributes.form_response_id,
920
- formType: data.attributes.form_type
921
- }
922
- };
923
- return {
924
- eventId: data.event_id,
925
- createdAt: data.created_at,
926
- category: UserEventCategory$1.AppLoaded
927
- };
928
- };
929
-
930
- //#endregion
931
- //#region src/application/utils/analyticsUtils.ts
932
- const NORMALIZED_ADD_TO_CART_EVENT_NAMES = ["addtocart", "addedtocart"];
933
- const CHECK_DATA_LAYER_INTERVAL_MS = 500;
934
- const CHECK_DATA_LAYER_MAX_ATTEMPTS = 10;
935
- /**
936
- * Checks if a Google Analytics event is an add_to_cart event.
937
- *
938
- * @param event The event name to check.
939
- *
940
- * @returns True if the event is an add_to_cart event, false otherwise.
941
- */
942
- const isAddToCartEvent = (event) => {
943
- const normalizedEvent = event.replace(/[-_]/g, "").toLowerCase();
944
- return NORMALIZED_ADD_TO_CART_EVENT_NAMES.some((name) => normalizedEvent.includes(name));
945
- };
946
- /**
947
- * Tracks an add_to_cart event in Amplitude.
948
- *
949
- * @param event The event to track.
950
- */
951
- const handleAddToCartEvent = (event) => {
952
- let eventProps;
953
- if (isLegacyUAEcommerceEvent(event)) eventProps = {
954
- items: event.ecommerce.add.products.map((product) => ({
955
- item_name: product.name,
956
- item_category: product.category,
957
- price: product.price,
958
- quantity: product.quantity
959
- })),
960
- currency: event.ecommerce.add.currencyCode,
961
- event_format_version: "legacy_universal_analytics"
962
- };
963
- else if (isGA4EcommerceEvent(event)) eventProps = {
964
- items: event.ecommerce.items.map((item) => ({
965
- item_name: item.item_name,
966
- item_category: item.item_category,
967
- price: item.price,
968
- quantity: item.quantity
969
- })),
970
- currency: event.ecommerce.currency,
971
- event_format_version: "google_analytics_4"
972
- };
973
- else eventProps = {
974
- event_properties: { ...event },
975
- event_format_version: "unknown"
976
- };
977
- AmplitudeAdapter.trackEvent({
978
- eventName: SpiffyMetricsEventName.AddToCartClicked,
979
- eventProps
980
- });
981
- };
982
- /**
983
- * Wraps the window.dataLayer.push method to intercept add_to_cart events and send them to Amplitude.
984
- * This function runs on an interval until the dataLayer is available.
985
- */
986
- const initDataLayerWrapper = () => {
987
- let attempts = 0;
988
- const checkAndInitialize = () => {
989
- if (!window.dataLayer || !window.dataLayer.push) {
990
- attempts += 1;
991
- if (attempts >= CHECK_DATA_LAYER_MAX_ATTEMPTS) {
992
- logger_default.logDebug(`[spiffy-ai] dataLayer not available after ${CHECK_DATA_LAYER_MAX_ATTEMPTS} attempts`);
993
- return;
994
- }
995
- setTimeout(checkAndInitialize, CHECK_DATA_LAYER_INTERVAL_MS);
996
- return;
997
- }
998
- logger_default.logDebug("[spiffy-ai] dataLayer is available, wrapping push function...");
999
- const originalPush = window.dataLayer.push;
1000
- window.dataLayer.push = (args) => {
1001
- if (isBaseEcommerceEvent(args) && isAddToCartEvent(args.event)) handleAddToCartEvent(args);
1002
- originalPush.apply(window.dataLayer, [args]);
1003
- };
1004
- };
1005
- checkAndInitialize();
1006
- };
1007
- const initAmplitude = () => {
1008
- AmplitudeAdapter.getSingletonInstanceOf();
1009
- };
1010
-
1011
- //#endregion
1012
- //#region src/application/utils/coreContextToApiContext.ts
1013
- const coreContextToApiContext = (context) => ({
1014
- chat_id: context.chatId,
1015
- org_id: context.orgId,
1016
- user_id: context.userId,
1017
- org_short_name: context.orgShortName,
1018
- source: context.source,
1019
- env: context.env
1020
- });
1021
-
1022
- //#endregion
1023
- //#region src/application/utils/coreUserEventToApiUserEvent.ts
1024
- const coreUserEventToApiUserEvent = (data) => {
1025
- if (data.category === UserEventCategory$1.PdpVisit || data.category === UserEventCategory$1.AddToCart) return {
1026
- event_id: data.eventId,
1027
- created_at: data.createdAt,
1028
- category: data.category,
1029
- attributes: {
1030
- product_id: data.attributes.productId,
1031
- parent_product_id: data.attributes.parentProductId,
1032
- url: data.attributes.url
1033
- }
1034
- };
1035
- if (data.category === UserEventCategory$1.PlpVisit) return {
1036
- event_id: data.eventId,
1037
- created_at: data.createdAt,
1038
- category: data.category,
1039
- attributes: {
1040
- category: PLPAttributeCategory.Id,
1041
- attributes: { id: data.attributes.attributes.id }
1042
- }
1043
- };
1044
- if (data.category === UserEventCategory$1.QueryTyped) return {
1045
- event_id: data.eventId,
1046
- created_at: data.createdAt,
1047
- category: data.category,
1048
- attributes: { query: data.attributes.query }
1049
- };
1050
- if (data.category === UserEventCategory$1.Search) return {
1051
- event_id: data.eventId,
1052
- created_at: data.createdAt,
1053
- category: data.category,
1054
- attributes: {
1055
- search_term: data.attributes.searchTerm,
1056
- selected_filters: data.attributes.selectedFilters
1057
- }
1058
- };
1059
- if (data.category === UserEventCategory$1.SuggestionClicked) return {
1060
- event_id: data.eventId,
1061
- created_at: data.createdAt,
1062
- category: data.category,
1063
- attributes: { suggestion_id: data.attributes.suggestionId }
1064
- };
1065
- if (data.category === UserEventCategory$1.PageVisit) return {
1066
- event_id: data.eventId,
1067
- created_at: data.createdAt,
1068
- category: data.category,
1069
- attributes: {
1070
- url: data.attributes.url,
1071
- page_visit_category: data.attributes.pageVisitCategory
1072
- }
1073
- };
1074
- if (data.category === UserEventCategory$1.FormSubmitted) return {
1075
- event_id: data.eventId,
1076
- created_at: data.createdAt,
1077
- category: data.category,
1078
- attributes: {
1079
- filled_schema: { ...data.attributes.filledSchema },
1080
- form_response_id: data.attributes.formResponseId,
1081
- form_type: data.attributes.formType
1082
- }
1083
- };
1084
- return {
1085
- event_id: data.eventId,
1086
- created_at: data.createdAt,
1087
- category: data.category
1088
- };
1089
- };
1090
-
1091
- //#endregion
1092
- //#region src/application/utils/divideArray.ts
1093
- const divideArray = (array, size) => {
1094
- const rows = [];
1095
- for (let i = 0; i < size; i += 1) rows.push(array.filter((_, index) => index % size === i));
1096
- return rows;
1097
- };
1098
-
1099
- //#endregion
1100
- //#region src/application/utils/mutationHelper.ts
1101
- const compareTokens = (original, comparison) => {
1102
- const originalTokens = new Set(original.split(" "));
1103
- const comparisonTokens = new Set(comparison.split(" "));
1104
- return [...originalTokens].filter((token) => !comparisonTokens.has(token));
1105
- };
1106
- var MutationHelper = class {
1107
- static fireClassChange(record, node, fn) {
1108
- if (node && record.oldValue !== node?.classList.value) fn(node?.classList);
1109
- }
1110
- static fireClassAdded(record, node, classMap) {
1111
- if (node && record.oldValue) compareTokens(node?.classList.value, record.oldValue).forEach((className) => classMap.get(className)?.());
1112
- }
1113
- static fireClassRemoved(record, node, classMap) {
1114
- if (node && record.oldValue) compareTokens(record.oldValue, node?.classList.value).forEach((className) => classMap.get(className)?.());
1115
- }
1116
- static fireSubtreeChange(nodes, fn) {
1117
- nodes.length && fn?.(nodes);
1118
- }
1119
- static isClass(mutation) {
1120
- return mutation.type === "attributes" && mutation.attributeName === "class";
1121
- }
1122
- static isChildList(mutation) {
1123
- return mutation.type === "childList";
1124
- }
1125
- };
1126
-
1127
- //#endregion
1128
- //#region src/application/utils/elementObserver.ts
1129
- /**
1130
- * The `ElementObserver` class monitors all changes related to the specific element it is responsible for.
1131
- * It is automatically instantiated by the `useElementObserver` hook, which manages all instances of this class.
1132
- *
1133
- * How it works:
1134
- *
1135
- * Each instance of `ElementObserver` holds several pieces of information related to the node it is monitoring,
1136
- * such as the node's selector and its `MutationObserver`. This class is responsible for translating raw node
1137
- * changes into a more user-friendly format. For example, when the node is added to the DOM, the `ElementObserver`
1138
- * is notified by the `DOMObserver`, which triggers the `onAdd` callback function on the respective `useElementObserver`
1139
- * instance.
1140
- *
1141
- * Instances of `ElementObserver` are fully managed by the `useElementObserver` hook, requiring no additional configuration.
1142
- * When the hook is destroyed, its corresponding `ElementObserver` instance is automatically removed.
1143
- *
1144
- */
1145
- var ElementObserver = class {
1146
- constructor(selector) {
1147
- this.selector = selector;
1148
- this.mutation = null;
1149
- this.node = null;
1150
- this.eventListeners = /* @__PURE__ */ new Map();
1151
- this.classAdded = /* @__PURE__ */ new Map();
1152
- this.classRemoved = /* @__PURE__ */ new Map();
1153
- this.nodeDisplay = "block";
1154
- this.addFn = () => {};
1155
- this.removeFn = () => {};
1156
- this.changeFn = () => {};
1157
- this.classChangeFn = () => {};
1158
- this.addChildFn = void 0;
1159
- this.removeChildFn = void 0;
1160
- this.resetFn = () => {};
1161
- }
1162
- handleAttributes(mutationRecord) {
1163
- mutationRecord.filter(MutationHelper.isClass).forEach((mutation) => {
1164
- MutationHelper.fireClassChange(mutation, this.node, this.classChangeFn);
1165
- MutationHelper.fireClassAdded(mutation, this.node, this.classAdded);
1166
- MutationHelper.fireClassRemoved(mutation, this.node, this.classRemoved);
1167
- });
1168
- }
1169
- handleChildList(mutationRecord) {
1170
- if (!this.addChildFn && !this.removeChildFn) return;
1171
- mutationRecord.filter(MutationHelper.isChildList).forEach((mutation) => {
1172
- MutationHelper.fireSubtreeChange(mutation.addedNodes, this.addChildFn);
1173
- MutationHelper.fireSubtreeChange(mutation.removedNodes, this.removeChildFn);
1174
- });
1175
- }
1176
- addInitialListeners() {
1177
- this.eventListeners.forEach((v, k) => this.node?.addEventListener(k, v));
1178
- }
1179
- clearEventListeners() {
1180
- this.eventListeners.forEach((v, k) => this.node?.removeEventListener(k, v));
1181
- this.eventListeners.clear();
1182
- }
1183
- renew(newNode) {
1184
- if (newNode) {
1185
- this.destroy();
1186
- this.watch(newNode);
1187
- }
1188
- }
1189
- getSelector() {
1190
- return this.selector;
1191
- }
1192
- getNode() {
1193
- return this.node;
1194
- }
1195
- synchronize() {
1196
- const parsedNode = this.getSelector().parse();
1197
- if (this.getNode() !== parsedNode) {
1198
- this.renew(parsedNode);
1199
- return;
1200
- }
1201
- if (!this.getNode() && parsedNode) {
1202
- this.watch(parsedNode);
1203
- return;
1204
- }
1205
- if (this.getNode() && !parsedNode) this.destroy();
1206
- }
1207
- init() {
1208
- const node = this.getSelector().parse();
1209
- if (node) this.watch(node);
1210
- }
1211
- watch(node) {
1212
- if (!this.mutation) {
1213
- this.mutation = new MutationObserver((mutationRecord) => {
1214
- this.handleAttributes(mutationRecord);
1215
- this.handleChildList(mutationRecord);
1216
- this.changeFn(this.node);
1217
- });
1218
- this.mutation.observe(node, {
1219
- childList: true,
1220
- subtree: true,
1221
- attributes: true,
1222
- attributeOldValue: true
1223
- });
1224
- this.node = node;
1225
- this.addFn(this.node);
1226
- this.addInitialListeners();
1227
- }
1228
- }
1229
- destroy() {
1230
- this.resetFn();
1231
- this.removeFn(this.node);
1232
- this.mutation?.disconnect();
1233
- this.clearEventListeners();
1234
- this.classAdded.clear();
1235
- this.classRemoved.clear();
1236
- this.mutation = null;
1237
- this.node = null;
1238
- }
1239
- render(fn) {
1240
- if (this.node) return createPortal(fn(), this.node);
1241
- }
1242
- fire(event) {
1243
- if (this.node) this.node.dispatchEvent(new MouseEvent(event, {
1244
- bubbles: true,
1245
- cancelable: true,
1246
- view: window
1247
- }));
1248
- }
1249
- show() {
1250
- const display = this.node?.style.display;
1251
- if (this.node && display === "none") this.node.style.display = this.nodeDisplay || "block";
1252
- }
1253
- hide() {
1254
- const display = this.node?.style.display;
1255
- if (this.node && display !== "none") {
1256
- this.nodeDisplay = display || "block";
1257
- this.node.style.display = "none";
1258
- }
1259
- }
1260
- registerEvent(event, fn) {
1261
- if (this.node) {
1262
- const previousFn = this.eventListeners.get(event);
1263
- if (previousFn) this.node.removeEventListener(event, previousFn);
1264
- this.node.addEventListener(event, fn);
1265
- }
1266
- this.eventListeners.set(event, fn);
1267
- }
1268
- registerOnReset(fn) {
1269
- this.resetFn = fn;
1270
- }
1271
- registerOnChange(fn) {
1272
- this.changeFn = fn;
1273
- }
1274
- registerOnAdd(fn) {
1275
- this.addFn = fn;
1276
- }
1277
- registerOnRemove(fn) {
1278
- this.removeFn = fn;
1279
- }
1280
- registerOnclassChange(fn) {
1281
- this.classChangeFn = fn;
1282
- }
1283
- registerOnAddChild(fn) {
1284
- this.addChildFn = fn;
1285
- }
1286
- registerOnRemoveChild(fn) {
1287
- this.removeChildFn = fn;
1288
- }
1289
- registerOnClassAdded(className, fn) {
1290
- this.classAdded.set(className, fn);
1291
- }
1292
- registerOnClassRemoved(className, fn) {
1293
- this.classRemoved.set(className, fn);
1294
- }
1295
- };
1296
-
1297
- //#endregion
1298
- //#region src/application/utils/domObserver.ts
1299
- /**
1300
- * This class manages a `MutationObserver` for the `document.body`. It monitors nodes that are
1301
- * added or removed from the DOM and notifies the observers for each observable element
1302
- * when they are ready to be watched.
1303
- *
1304
- * How that works:
1305
- *
1306
- * When the `observe` function is called, it attaches a `MutationObserver` to the `document.body` element.
1307
- * All changes to `document.body` are tracked by this observer. When changes are detected, the `MutationObserver`
1308
- * iterates through all added and removed nodes and checks if each node exists in the main map of observable elements.
1309
- *
1310
- * If a match is found, it notifies the corresponding `ElementObserver` instance to start monitoring changes for that element.
1311
- *
1312
- * The primary `MutationObserver` remains active until the `destroy` function is called. Calling `destroy` will disconnect all
1313
- * individual element observers and release any associated resources.
1314
- *
1315
- * There is no need to explicitly call the `observe` function. It is automatically invoked when a `useElementObserver` hook is instantiated.
1316
- *
1317
- */
1318
- var DOMObserver = class {
1319
- static {
1320
- this.listeners = /* @__PURE__ */ new Map();
1321
- }
1322
- static notifyAdition(records, nodeMapping) {
1323
- records.forEach((record) => record.addedNodes.forEach((node) => {
1324
- nodeMapping.get(node)?.watch(node);
1325
- nodeMapping.delete(node);
1326
- }));
1327
- }
1328
- static notifyRemoval(records, nodeMapping) {
1329
- records.forEach((record) => record.removedNodes.forEach((node) => {
1330
- nodeMapping.get(node)?.destroy();
1331
- nodeMapping.delete(node);
1332
- }));
1333
- }
1334
- static notifyChildrenChanges(nodeMapping) {
1335
- Array.from(nodeMapping.values()).forEach((observer) => observer.synchronize());
1336
- }
1337
- static mapNodeInstancesToListeners() {
1338
- const nodeMapping = /* @__PURE__ */ new Map();
1339
- this.listeners.forEach((observer) => {
1340
- const node = observer.getNode() || observer.getSelector()?.parse();
1341
- if (node) nodeMapping.set(node, observer);
1342
- });
1343
- return nodeMapping;
1344
- }
1345
- static add(selector) {
1346
- const node = selector.getPattern();
1347
- let elementObserver = this.listeners.get(node);
1348
- if (elementObserver) return elementObserver;
1349
- elementObserver = new ElementObserver(selector);
1350
- this.listeners.set(node, elementObserver);
1351
- return elementObserver;
1352
- }
1353
- static remove(selector) {
1354
- const node = selector.getPattern();
1355
- this.listeners.get(node)?.destroy();
1356
- this.listeners.delete(node);
1357
- }
1358
- static observe() {
1359
- if (!this.documentObserver) {
1360
- this.documentObserver = new MutationObserver((mutations) => {
1361
- const nodeMapping = this.mapNodeInstancesToListeners();
1362
- this.notifyAdition(mutations, nodeMapping);
1363
- this.notifyRemoval(mutations, nodeMapping);
1364
- this.notifyChildrenChanges(nodeMapping);
1365
- });
1366
- this.documentObserver.observe(document.body, {
1367
- childList: true,
1368
- subtree: true
1369
- });
1370
- }
1371
- }
1372
- static destroy() {
1373
- this.documentObserver?.disconnect();
1374
- this.listeners.forEach((listener) => listener.destroy());
1375
- this.listeners.clear();
1376
- this.documentObserver = null;
1377
- }
1378
- };
1379
-
1380
- //#endregion
1381
- //#region src/application/utils/imageFilter.ts
1382
- const getRecentProductImageUrls = (lastMessages, currentProductId) => {
1383
- const productMessages = lastMessages.filter((message) => message.type === MessageType.Product && message.metadata?.imageUrl).map((m) => m);
1384
- return [...productMessages.filter((m) => m.metadata?.id === currentProductId), ...productMessages.filter((m) => m.metadata?.id !== currentProductId)].map((m) => m.metadata.imageUrl);
1385
- };
1386
-
1387
- //#endregion
1388
- //#region src/application/utils/merchantUtils.ts
1389
- const prepareMerchantPage = () => {
1390
- let metaViewport = document.querySelector("meta[name='viewport']");
1391
- if (metaViewport) {
1392
- const content = metaViewport.getAttribute("content");
1393
- if (!content?.includes("maximum-scale=1")) metaViewport.setAttribute("content", `${content}, maximum-scale=1`);
1394
- return;
1395
- }
1396
- metaViewport = document.createElement("meta");
1397
- metaViewport.setAttribute("name", "viewport");
1398
- metaViewport.setAttribute("content", "width=device-width, initial-scale=1, maximum-scale=1");
1399
- document.head.appendChild(metaViewport);
1400
- };
1401
-
1402
- //#endregion
1403
- //#region src/application/utils/messageFromFormSubmittedEvent.ts
1404
- const messageFromFormSubmittedEvent = (event, formResponseAttributes) => {
1405
- if (event.category !== UserEventCategory$1.FormSubmitted) return;
1406
- const formStringContents = Object.entries(formResponseAttributes.schema.properties).map(([key, value]) => `${value.title}: ${event.attributes.filledSchema[key]}`).join("\n");
1407
- return {
1408
- id: event.eventId,
1409
- role: MessageRole.User,
1410
- type: MessageType.QueryTyped,
1411
- createdAt: event.createdAt,
1412
- metadata: { content: formStringContents }
1413
- };
1414
- };
1415
-
1416
- //#endregion
1417
- //#region src/application/utils/messageFromQueryEvent.ts
1418
- /**
1419
- * Transforms a query UserEvent object into a Message object for presentation.
1420
- *
1421
- * @param event The user event object received from the server
1422
- *
1423
- * @returns A Message if the event is a query event, otherwise undefined
1424
- */
1425
- const messageFromQueryEvent = (event) => {
1426
- if (event.category === UserEventCategory$1.QueryTyped) return {
1427
- id: event.eventId,
1428
- role: MessageRole.User,
1429
- type: MessageType.QueryTyped,
1430
- createdAt: event.createdAt,
1431
- metadata: { content: event.attributes.query }
1432
- };
1433
- if (event.category === UserEventCategory$1.Search) return {
1434
- id: event.eventId,
1435
- role: MessageRole.User,
1436
- type: MessageType.Search,
1437
- createdAt: event.createdAt,
1438
- metadata: {
1439
- searchTerm: event.attributes.searchTerm || "",
1440
- selectedFilters: event.attributes.selectedFilters || []
1441
- }
1442
- };
1443
- };
1444
-
1445
- //#endregion
1446
- //#region src/application/utils/messageFromResponse.ts
1447
- /**
1448
- * Transforms a server Response object into a Message object for presentation.
1449
- *
1450
- * @param response The response object received from the server containing model generated content
1451
- *
1452
- * @returns A Message if the response contains known attributes, undefined otherwise
1453
- */
1454
- const messageFromResponse = (response) => {
1455
- if (response == null) return;
1456
- if (response.category === ResponseCategory.Text) return {
1457
- id: response.id,
1458
- createdAt: response.createdAt,
1459
- type: MessageType.Text,
1460
- role: MessageRole.Assistant,
1461
- metadata: { content: response.attributes.content }
1462
- };
1463
- if (response.category === ResponseCategory.Product) return {
1464
- id: response.id,
1465
- createdAt: response.createdAt,
1466
- role: MessageRole.Assistant,
1467
- type: MessageType.Product,
1468
- metadata: { ...response.attributes }
1469
- };
1470
- if (response.category === ResponseCategory.Review) return {
1471
- id: response.id,
1472
- createdAt: response.createdAt,
1473
- type: MessageType.Review,
1474
- role: MessageRole.Assistant,
1475
- metadata: {
1476
- review: response.attributes.review,
1477
- reviewer: response.attributes.reviewer,
1478
- stars: response.attributes.stars,
1479
- title: response.attributes.title,
1480
- richInformation: response.attributes.richInformation
1481
- }
1482
- };
1483
- if (response.category === ResponseCategory.Separator) return {
1484
- id: response.id,
1485
- createdAt: response.createdAt,
1486
- type: MessageType.Separator,
1487
- role: MessageRole.Assistant
1488
- };
1489
- if (response.category === ResponseCategory.Page) return {
1490
- id: response.id,
1491
- createdAt: response.createdAt,
1492
- role: MessageRole.Assistant,
1493
- type: MessageType.Page,
1494
- metadata: { ...response.attributes }
1495
- };
1496
- if (response.category === ResponseCategory.ProductSearch) return {
1497
- id: response.id,
1498
- createdAt: response.createdAt,
1499
- role: MessageRole.Assistant,
1500
- type: MessageType.ProductSearch,
1501
- metadata: { ...response.attributes }
1502
- };
1503
- if (response.category === ResponseCategory.ProductSearchFilter) return {
1504
- id: response.id,
1505
- createdAt: response.createdAt,
1506
- role: MessageRole.Assistant,
1507
- type: MessageType.ProductSearchFilter,
1508
- metadata: { ...response.attributes }
1509
- };
1510
- if (response.category === ResponseCategory.Form) return {
1511
- id: response.id,
1512
- createdAt: response.createdAt,
1513
- role: MessageRole.Assistant,
1514
- type: MessageType.Form,
1515
- metadata: {
1516
- formType: response.attributes.formCategory?.formType,
1517
- fields: Object.entries(response.attributes.schema.properties).map(([key, value]) => ({
1518
- key,
1519
- title: value.title,
1520
- type: value.type,
1521
- format: value.format,
1522
- required: response.attributes.schema.required.includes(key)
1523
- }))
1524
- }
1525
- };
1526
- if (response.category === ResponseCategory.Order) return {
1527
- id: response.id,
1528
- createdAt: response.createdAt,
1529
- role: MessageRole.Assistant,
1530
- type: MessageType.Order,
1531
- metadata: { ...response.attributes }
1532
- };
1533
- };
1534
-
1535
- //#endregion
1536
- //#region src/application/utils/messageFromSuggestionEvent.ts
1537
- /**
1538
- * Transforms a UserEvent object into a Message object for presentation.
1539
- *
1540
- * @param event The UserEvent object received from the server
1541
- * @param suggestions A list of generated suggestions to match the event to
1542
- *
1543
- * @returns A Message if the event is a suggestion click event, undefined otherwise
1544
- */
1545
- const messageFromSuggestionEvent = (event, suggestions) => {
1546
- if (event.category === UserEventCategory$1.SuggestionClicked) {
1547
- const { suggestionId } = event.attributes;
1548
- return {
1549
- id: event.eventId,
1550
- role: MessageRole.User,
1551
- type: MessageType.SuggestionClicked,
1552
- createdAt: event.createdAt,
1553
- metadata: {
1554
- suggestionId,
1555
- suggestionContent: suggestions.find((s) => s.id === suggestionId)?.content ?? ""
1556
- }
1557
- };
1558
- }
1559
- };
1560
-
1561
- //#endregion
1562
- //#region src/application/utils/nextMessageRequestToApiRequest.ts
1563
- const messageRequestToCommerceMessageRequest = (data) => ({
1564
- context: {
1565
- chat_id: data.context.chatId,
1566
- org_id: data.context.orgId,
1567
- org_short_name: data.context.orgShortName,
1568
- user_id: data.context.userId,
1569
- source: data.context.source,
1570
- env: data.context.env
1571
- },
1572
- id: data.id,
1573
- feature_flags: data.featureFlags,
1574
- user_events: data.userEvents?.map((userEvent) => coreUserEventToApiUserEvent(userEvent)),
1575
- generation_params: {
1576
- model: data.generationParams?.model,
1577
- max_tokens: data.generationParams?.maxTokens,
1578
- stop: data.generationParams?.stop,
1579
- stream: data.generationParams?.stream,
1580
- temperature: data.generationParams?.temperature,
1581
- top_p: data.generationParams?.topP,
1582
- num_suggestions: data.generationParams?.numSuggestions,
1583
- response_system_prompt: data.generationParams?.responseSystemPrompt,
1584
- suggestion_system_prompt: data.generationParams?.suggestionSystemPrompt,
1585
- response_caching: data.generationParams?.responseCaching
1586
- }
1587
- });
1588
-
1589
- //#endregion
1590
- //#region src/application/utils/nodeSelector.ts
1591
- var NodeSelector = class {
1592
- constructor(pattern) {
1593
- this.pattern = pattern;
1594
- this.root = document;
1595
- }
1596
- getPattern() {
1597
- return this.pattern;
1598
- }
1599
- setRoot(root) {
1600
- this.root = root;
1601
- }
1602
- getRoot() {
1603
- return this.root;
1604
- }
1605
- };
1606
- var QuerySelector = class extends NodeSelector {
1607
- parse() {
1608
- return this.getRoot().querySelector(this.getPattern());
1609
- }
1610
- };
1611
- var IDSelector = class extends NodeSelector {
1612
- parse() {
1613
- return this.getRoot().getElementById(this.getPattern());
1614
- }
1615
- };
1616
- var XpathSelector = class extends NodeSelector {
1617
- parse() {
1618
- return this.getRoot()?.evaluate(this.getPattern(), this.getRoot(), null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)?.singleNodeValue;
1619
- }
1620
- };
1621
- var ChainSelector = class extends NodeSelector {
1622
- parse() {
1623
- let selectorIndex = 0;
1624
- const selectors = this.getPattern().split("@");
1625
- const lastIndex = selectors.length - 1;
1626
- const parseChain = (pattern, prevNode) => {
1627
- const selector = SelectorFactory.parse(pattern);
1628
- if (prevNode) selector.setRoot(prevNode);
1629
- const currentNode = selector.parse();
1630
- if (selectorIndex === lastIndex) return currentNode;
1631
- let node = currentNode || document;
1632
- if (currentNode?.shadowRoot) node = currentNode.shadowRoot;
1633
- if (currentNode?.contentWindow) node = currentNode.contentWindow?.document;
1634
- return parseChain(selectors[++selectorIndex].trim(), node);
1635
- };
1636
- return parseChain(selectors[selectorIndex].trim());
1637
- }
1638
- };
1639
- var Empty = class extends NodeSelector {
1640
- constructor() {
1641
- super("");
1642
- }
1643
- parse() {
1644
- return null;
1645
- }
1646
- };
1647
- var SelectorFactory = class {
1648
- static parse(composedSelector) {
1649
- if (!composedSelector) return new Empty();
1650
- const split = composedSelector.split("|");
1651
- const type = split[0];
1652
- const selector = split[1];
1653
- switch (type) {
1654
- case "id": return this.id(selector);
1655
- case "query": return this.query(selector);
1656
- case "xpath": return this.xpath(selector);
1657
- default: return new Empty();
1658
- }
1659
- }
1660
- static check(selector) {
1661
- return selector ?? new Empty();
1662
- }
1663
- static chain(pattern) {
1664
- return pattern ? new ChainSelector(pattern) : new Empty();
1665
- }
1666
- static id(pattern) {
1667
- return pattern ? new IDSelector(pattern) : new Empty();
1668
- }
1669
- static query(pattern) {
1670
- return pattern ? new QuerySelector(pattern) : new Empty();
1671
- }
1672
- static xpath(pattern) {
1673
- return pattern ? new XpathSelector(pattern) : new Empty();
1674
- }
1675
- };
1676
-
1677
- //#endregion
1678
- //#region src/application/utils/overrides.ts
1679
- function isPlainObject(x) {
1680
- return !!x && typeof x === "object" && !Array.isArray(x) && !(x instanceof Date) && !(x instanceof RegExp);
1681
- }
1682
- function isReplace(x) {
1683
- return !!x && typeof x === "object" && "$replace" in x;
1684
- }
1685
- function isDelete(x) {
1686
- return !!x && typeof x === "object" && x.$delete === true;
1687
- }
1688
- function isPrimitiveValue(x) {
1689
- const t = typeof x;
1690
- return x === null || t === "string" || t === "number" || t === "boolean" || t === "bigint" || t === "symbol" || t === "undefined";
1691
- }
1692
- function isArrayOfPrimitives(arr) {
1693
- if (arr.length === 0) return false;
1694
- for (let i = 0; i < arr.length; i += 1) {
1695
- const v = arr[i];
1696
- if (v !== void 0 && !isPrimitiveValue(v)) return false;
1697
- }
1698
- return true;
1699
- }
1700
- function mergeAny(baseAny, patchAny, opts) {
1701
- if (isReplace(patchAny)) return patchAny.$replace;
1702
- if (isDelete(patchAny)) return void 0;
1703
- if (Array.isArray(baseAny)) {
1704
- if (Array.isArray(patchAny)) {
1705
- const baseArr = baseAny;
1706
- const patchArr = patchAny;
1707
- if (opts.arrayStrategy === "replace" || isArrayOfPrimitives(baseArr) || isArrayOfPrimitives(patchArr)) return patchAny;
1708
- const out = baseArr.slice();
1709
- const max = Math.max(out.length, patchArr.length);
1710
- for (let i = 0; i < max; i += 1) {
1711
- const pVal = patchArr[i];
1712
- if (pVal !== void 0) out[i] = mergeAny(out[i], pVal, opts);
1713
- }
1714
- return out;
1715
- }
1716
- return baseAny;
1717
- }
1718
- if (isPlainObject(baseAny) && isPlainObject(patchAny)) {
1719
- const baseObj = baseAny;
1720
- const patchObj = patchAny;
1721
- const out = { ...baseObj };
1722
- for (const key of Object.keys(patchObj)) {
1723
- const pVal = patchObj[key];
1724
- if (pVal === void 0) {} else if (opts.nullDeletes && pVal === null) delete out[key];
1725
- else if (isReplace(pVal)) out[key] = pVal.$replace;
1726
- else if (isDelete(pVal)) delete out[key];
1727
- else out[key] = mergeAny(baseObj?.[key], pVal, opts);
1728
- }
1729
- return out;
1730
- }
1731
- return patchAny ?? baseAny;
1732
- }
1733
- function applyOverrides(base, patch, opts = {}) {
1734
- const { arrayStrategy = "mergeByIndex", nullDeletes = false } = opts;
1735
- if (isReplace(patch)) return patch.$replace;
1736
- if (isDelete(patch)) return void 0;
1737
- if (Array.isArray(base)) {
1738
- if (isReplace(patch)) return patch.$replace;
1739
- if (Array.isArray(patch)) {
1740
- if (arrayStrategy === "replace") return patch;
1741
- const out = base.slice();
1742
- const max = Math.max(out.length, patch.length);
1743
- for (let i = 0; i < max; i += 1) {
1744
- const pVal = patch[i];
1745
- if (pVal !== void 0) out[i] = mergeAny(out[i], pVal, opts);
1746
- }
1747
- return out;
1748
- }
1749
- return base;
1750
- }
1751
- if (isPlainObject(base) && isPlainObject(patch)) {
1752
- const out = { ...base };
1753
- const patchObj = patch;
1754
- for (const key of Object.keys(patchObj)) {
1755
- const pVal = patchObj[key];
1756
- if (pVal === void 0) {} else if (nullDeletes && pVal === null) delete out[key];
1757
- else if (isReplace(pVal)) out[key] = pVal.$replace;
1758
- else if (isDelete(pVal)) delete out[key];
1759
- else {
1760
- const bVal = base[key];
1761
- out[key] = mergeAny(bVal, pVal, opts);
1762
- }
1763
- }
1764
- return out;
1765
- }
1766
- return patch ?? base;
1767
- }
1768
-
1769
- //#endregion
1770
- //#region src/application/utils/stringUtils.ts
1771
- var StringUtils = class StringUtils {
1772
- static isNullOrEmpty(value) {
1773
- const valueTrimmed = value?.trim();
1774
- return value === void 0 || valueTrimmed === "";
1775
- }
1776
- static trimToNull(value) {
1777
- const valueTrimmed = value?.trim();
1778
- return StringUtils.isNullOrEmpty(valueTrimmed) ? void 0 : valueTrimmed;
1779
- }
1780
- static capitalize(type) {
1781
- if (type === void 0) return "";
1782
- return type.charAt(0).toUpperCase() + type.substring(1);
1783
- }
1784
- /**
1785
- * Finds the first pattern in an array that matches a given URL.
1786
- * Patterns can include a single wildcard '*' which matches any sequence of characters.
1787
- *
1788
- * @param patterns
1789
- * @param urlToTest
1790
- * @returns
1791
- */
1792
- static findMatchingPattern(patterns, urlToTest) {
1793
- if (!urlToTest) return;
1794
- for (const pattern of patterns) if (urlToTest.pathname !== "/") {
1795
- const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
1796
- if ((/* @__PURE__ */ new RegExp(`^${regexPattern}$`)).test(urlToTest.pathname)) return pattern;
1797
- } else if (pattern.startsWith(urlToTest.hostname)) return pattern;
1798
- }
1799
- };
1800
-
1801
- //#endregion
1802
- //#region src/application/utils/supportedEventRequestToApiRequest.ts
1803
- const coreSupportedEventRequestToApiRequest = (coreSupportedEventRequest) => ({
1804
- id: coreSupportedEventRequest.id,
1805
- user_event: coreUserEventToApiUserEvent(coreSupportedEventRequest.userEvent),
1806
- context: coreContextToApiContext(coreSupportedEventRequest.context)
1807
- });
1808
-
1809
- //#endregion
1810
- //#region src/application/utils/validation.ts
1811
- const validateEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
1812
-
1813
- //#endregion
1814
- //#region src/application/models/guards/api/isApiPageResponseAttributes.ts
1815
- const isApiPageResponseAttributes = (obj) => {
1816
- if (obj == null || typeof obj !== "object") return false;
1817
- if ("title" in obj && obj.title != null && typeof obj.title !== "string") return false;
1818
- if ("description" in obj && typeof obj.description !== "string") return false;
1819
- if ("url" in obj && typeof obj.url !== "string") return false;
1820
- return true;
1821
- };
1822
-
1823
- //#endregion
1824
- //#region src/application/models/guards/api/isApiFormResponse.ts
1825
- /**
1826
- * Type guard to check if the provided data has the all of the properties (with the correct types) of
1827
- * a FormResponseAttribute
1828
- *
1829
- * @param data - The data to check
1830
- *
1831
- * @returns true if the data has the correct properties, false otherwise
1832
- */
1833
- const isApiFormResponseAttributes = (data) => {
1834
- if (data == null || typeof data !== "object") {
1835
- logger_default.logError("isApiFormResponseAttributes: data is null or not an object", void 0, { data });
1836
- return false;
1837
- }
1838
- if ("form_category" in data && typeof data.form_category !== "object") {
1839
- logger_default.logError("isApiFormResponseAttributes: form_category is not an object", void 0, { data });
1840
- return false;
1841
- }
1842
- if ("form_category" in data && typeof data.form_category === "object") {
1843
- if (!hasPropertyOfType(data.form_category, "form_type", "string") || !Object.values(FormType).includes(data.form_category.form_type)) {
1844
- logger_default.logError("isApiFormResponseAttributes: form_type is missing or not a valid form type", void 0, { data });
1845
- return false;
1846
- }
1847
- }
1848
- if (!hasPropertyOfType(data, "schema", "object")) {
1849
- logger_default.logError("isApiFormResponseAttributes: schema is missing or not an object", void 0, { data });
1850
- return false;
1851
- }
1852
- if (!hasPropertyOfType(data.schema, "properties", "object")) {
1853
- logger_default.logError("isApiFormResponseAttributes: schema.properties is missing or not an object", void 0, { data });
1854
- return false;
1855
- }
1856
- if (!hasPropertyOfType(data.schema, "required", "array")) {
1857
- logger_default.logError("isApiFormResponseAttributes: schema.required is missing or not an array", void 0, { data });
1858
- return false;
1859
- }
1860
- if (!data.schema.required.every((key) => typeof key === "string" && key in data.schema.properties)) {
1861
- logger_default.logError("isApiFormResponseAttributes: schema.required contains invalid property keys", void 0, { data });
1862
- return false;
1863
- }
1864
- return true;
1865
- };
1866
-
1867
- //#endregion
1868
- //#region src/application/models/guards/api/isApiOrderResponseAttributes.ts
1869
- const isApiOrderItemInfo = (data) => {
1870
- if (data == null || typeof data !== "object") {
1871
- logger_default.logError("OrderItemInfo must be an object", void 0, { data });
1872
- return false;
1873
- }
1874
- if (!hasPropertyOfType(data, "order_item_id", "string")) {
1875
- logger_default.logError("OrderItemInfo must have an order_item_id property", void 0, { data });
1876
- return false;
1877
- }
1878
- if (!hasPropertyOfType(data, "item_title", "string")) {
1879
- logger_default.logError("OrderItemInfo must have an item_title property", void 0, { data });
1880
- return false;
1881
- }
1882
- if (!hasPropertyOfType(data, "item_price", "number")) {
1883
- logger_default.logError("OrderItemInfo must have an item_price property", void 0, { data });
1884
- return false;
1885
- }
1886
- if (!hasPropertyOfType(data, "item_quantity", "number")) {
1887
- logger_default.logError("OrderItemInfo must have an item_quantity property", void 0, { data });
1888
- return false;
1889
- }
1890
- if (!hasPropertyOfType(data, "image", "string", true)) {
1891
- logger_default.logError("OrderItemInfo.image must be a string or null", void 0, { data });
1892
- return false;
1893
- }
1894
- if (!hasPropertyOfType(data, "fulfillment_display_status", "string", true)) {
1895
- logger_default.logError("OrderItemInfo.fulfillment_display_status must be a string or null", void 0, { data });
1896
- return false;
1897
- }
1898
- if (!hasPropertyOfType(data, "tracking_url", "string", true)) {
1899
- logger_default.logError("OrderItemInfo.tracking_url must be a string or null", void 0, { data });
1900
- return false;
1901
- }
1902
- if (!hasPropertyOfType(data, "delivered_at", "string", true)) {
1903
- logger_default.logError("OrderItemInfo.delivered_at must be a string or null", void 0, { data });
1904
- return false;
1905
- }
1906
- if (!hasPropertyOfType(data, "estimated_delivery_at", "string", true)) {
1907
- logger_default.logError("OrderItemInfo.estimated_delivery_at must be a string or null", void 0, { data });
1908
- return false;
1909
- }
1910
- if (!hasPropertyOfType(data, "in_transit_at", "string", true)) {
1911
- logger_default.logError("OrderItemInfo.in_transit_at must be a string or null", void 0, { data });
1912
- return false;
1913
- }
1914
- return true;
1915
- };
1916
- const isApiOrderResponseAttributes = (data) => {
1917
- if (data == null || typeof data !== "object") {
1918
- logger_default.logError("Order response attributes must be an object", void 0, { data });
1919
- return false;
1920
- }
1921
- if (!hasPropertyOfType(data, "created_at", "string")) {
1922
- logger_default.logError("Order response attributes must have a created_at property and have type string", void 0, { data });
1923
- return false;
1924
- }
1925
- if (!hasPropertyOfType(data, "latest_event_date", "string")) {
1926
- logger_default.logError("Order response attributes must have a latest_event_date property and have type string", void 0, { data });
1927
- return false;
1928
- }
1929
- if (!hasPropertyOfType(data, "line_items", "array") || !data.line_items.every((item) => isApiOrderItemInfo(item))) {
1930
- logger_default.logError("Order response attributes must have a line_items property with at least one order item", void 0, { data });
1931
- return false;
1932
- }
1933
- if (!hasPropertyOfType(data, "order_id", "string")) {
1934
- logger_default.logError("Order response attributes must have an order_id property and have type string", void 0, { data });
1935
- return false;
1936
- }
1937
- if (!hasPropertyOfType(data, "order_number", "string")) {
1938
- logger_default.logError("Order response attributes must have an order_number property and have type string", void 0, { data });
1939
- return false;
1940
- }
1941
- return true;
1942
- };
1943
-
1944
- //#endregion
1945
- //#region src/application/models/utils/stringToFulfillmentDisplayStatusEnumValue.ts
1946
- /**
1947
- * Converts a string to a FulfillmentDisplayStatus enum value.
1948
- *
1949
- * @param status - The string to convert.
1950
- *
1951
- * @returns The FulfillmentDisplayStatus enum value or undefined if the string
1952
- * does not map to a valid enum
1953
- */
1954
- const stringToFulfillmentDisplayStatusEnumValue = (status) => {
1955
- switch (status) {
1956
- case "ATTEMPTED_DELIVERY": return FulfillmentDisplayStatus.ATTEMPTED_DELIVERY;
1957
- case "CANCELED": return FulfillmentDisplayStatus.CANCELED;
1958
- case "CONFIRMED": return FulfillmentDisplayStatus.CONFIRMED;
1959
- case "DELIVERED": return FulfillmentDisplayStatus.DELIVERED;
1960
- case "FAILURE": return FulfillmentDisplayStatus.FAILURE;
1961
- case "FULFILLED": return FulfillmentDisplayStatus.FULFILLED;
1962
- case "IN_TRANSIT": return FulfillmentDisplayStatus.IN_TRANSIT;
1963
- case "LABEL_PRINTED": return FulfillmentDisplayStatus.LABEL_PRINTED;
1964
- case "LABEL_PURCHASED": return FulfillmentDisplayStatus.LABEL_PURCHASED;
1965
- case "LABEL_VOIDED": return FulfillmentDisplayStatus.LABEL_VOIDED;
1966
- case "MARKED_AS_FULFILLED": return FulfillmentDisplayStatus.MARKED_AS_FULFILLED;
1967
- case "NOT_DELIVERED": return FulfillmentDisplayStatus.NOT_DELIVERED;
1968
- case "OUT_FOR_DELIVERY": return FulfillmentDisplayStatus.OUT_FOR_DELIVERY;
1969
- case "PICKED_UP": return FulfillmentDisplayStatus.PICKED_UP;
1970
- case "READY_FOR_PICKUP": return FulfillmentDisplayStatus.READY_FOR_PICKUP;
1971
- case "SUBMITTED": return FulfillmentDisplayStatus.SUBMITTED;
1972
- case "IN_PROGRESS": return FulfillmentDisplayStatus.IN_PROGRESS;
1973
- case "ON_HOLD": return FulfillmentDisplayStatus.ON_HOLD;
1974
- case "OPEN": return FulfillmentDisplayStatus.OPEN;
1975
- case "PARTIALLY_FULFILLED": return FulfillmentDisplayStatus.PARTIALLY_FULFILLED;
1976
- case "PENDING_FULFILLMENT": return FulfillmentDisplayStatus.PENDING_FULFILLMENT;
1977
- case "REQUEST_DECLINED": return FulfillmentDisplayStatus.REQUEST_DECLINED;
1978
- case "RESTOCKED": return FulfillmentDisplayStatus.RESTOCKED;
1979
- case "SCHEDULED": return FulfillmentDisplayStatus.SCHEDULED;
1980
- case "UNFULFILLED": return FulfillmentDisplayStatus.UNFULFILLED;
1981
- default: return;
1982
- }
1983
- };
1984
-
1985
- //#endregion
1986
- //#region src/application/models/guards/api/isApiProductSearchFilterAttributes.ts
1987
- const isApiProductSearchFilterResponseAttributes = (attributes) => {
1988
- if (attributes == null || typeof attributes !== "object") return false;
1989
- if ("filter_name" in attributes && typeof attributes.filter_name !== "string") return false;
1990
- return true;
1991
- };
1992
-
1993
- //#endregion
1994
- //#region src/application/models/validators/validateResponse.ts
1995
- const richInformationFromCommerceRichInformation = (data) => ({
1996
- cons: data.cons,
1997
- pros: data.pros,
1998
- reviewDate: data.review_date,
1999
- reviewerTitle: data.reviewer_title,
2000
- productFamiliarity: data.product_familiarity
2001
- });
2002
- const validateResponse = (data) => {
2003
- if (!isApiResponse(data)) return;
2004
- if (data.category === ResponseCategory.Text && isApiTextResponseAttributes(data.attributes)) return {
2005
- id: data.id,
2006
- createdAt: data.created_at,
2007
- category: ResponseCategory.Text,
2008
- attributes: { content: data.attributes.content }
2009
- };
2010
- if (data.category === ResponseCategory.Product && isApiProductResponseAttributes(data.attributes)) return {
2011
- id: data.id,
2012
- createdAt: data.created_at,
2013
- category: ResponseCategory.Product,
2014
- attributes: {
2015
- id: data.attributes.id,
2016
- description: data.attributes.description,
2017
- imageUrl: data.attributes.image_url,
2018
- imageUrls: data.attributes.image_urls,
2019
- title: data.attributes.title,
2020
- url: data.attributes.url,
2021
- originalPrice: data.attributes.original_price,
2022
- salePrice: data.attributes.sale_price,
2023
- averageRating: data.attributes.average_rating,
2024
- numberReviews: data.attributes.number_reviews,
2025
- metadata: data.attributes.metadata,
2026
- isForGrid: data.attributes.is_for_grid,
2027
- colors: data.attributes.colors,
2028
- sizes: data.attributes.sizes,
2029
- filters: data.attributes.filters
2030
- }
2031
- };
2032
- if (data.category === ResponseCategory.Review && isApiReviewResponseAttributes(data.attributes)) return {
2033
- id: data.id,
2034
- createdAt: data.created_at,
2035
- category: ResponseCategory.Review,
2036
- attributes: {
2037
- id: data.attributes.id,
2038
- productId: data.attributes.product_id,
2039
- title: data.attributes.title,
2040
- reviewer: data.attributes.reviewer,
2041
- review: data.attributes.review,
2042
- stars: data.attributes.stars,
2043
- richInformation: data.attributes.rich_information ? richInformationFromCommerceRichInformation(data.attributes.rich_information) : void 0
2044
- }
2045
- };
2046
- if (data.category === ResponseCategory.Separator) return {
2047
- id: data.id,
2048
- createdAt: data.created_at,
2049
- category: ResponseCategory.Separator
2050
- };
2051
- if (data.category === ResponseCategory.Page && isApiPageResponseAttributes(data.attributes)) return {
2052
- id: data.id,
2053
- createdAt: data.created_at,
2054
- category: ResponseCategory.Page,
2055
- attributes: {
2056
- id: data.attributes.id,
2057
- title: data.attributes.title,
2058
- description: data.attributes.description,
2059
- url: data.attributes.url
2060
- }
2061
- };
2062
- if (data.category === ResponseCategory.Form && isApiFormResponseAttributes(data.attributes)) return {
2063
- id: data.id,
2064
- createdAt: data.created_at,
2065
- category: ResponseCategory.Form,
2066
- attributes: {
2067
- formCategory: data.attributes.form_category ? { formType: data.attributes.form_category.form_type } : void 0,
2068
- schema: {
2069
- properties: data.attributes.schema.properties,
2070
- required: data.attributes.schema.required.map(String)
2071
- }
2072
- }
2073
- };
2074
- if (data.category === ResponseCategory.ProductSearch && isApiProductSearchResponseAttributes(data.attributes)) return {
2075
- id: data.id,
2076
- createdAt: data.created_at,
2077
- category: ResponseCategory.ProductSearch,
2078
- attributes: {
2079
- generatedQuery: data.attributes.generated_query,
2080
- productCount: data.attributes.product_count
2081
- }
2082
- };
2083
- if (data.category === ResponseCategory.ProductSearchFilter && isApiProductSearchFilterResponseAttributes(data.attributes)) return {
2084
- id: data.id,
2085
- createdAt: data.created_at,
2086
- category: ResponseCategory.ProductSearchFilter,
2087
- attributes: { filterName: data.attributes.filter_name }
2088
- };
2089
- if (data.category === ResponseCategory.Order && isApiOrderResponseAttributes(data.attributes)) return {
2090
- id: data.id,
2091
- createdAt: data.created_at,
2092
- category: ResponseCategory.Order,
2093
- attributes: {
2094
- orderId: data.attributes.order_id,
2095
- orderNumber: data.attributes.order_number,
2096
- createdAt: data.attributes.created_at,
2097
- latestEventDate: data.attributes.latest_event_date,
2098
- lineItems: data.attributes.line_items.map((item) => ({
2099
- itemTitle: item.item_title,
2100
- itemPrice: item.item_price,
2101
- itemQuantity: item.item_quantity,
2102
- orderItemId: item.order_item_id,
2103
- image: item.image ?? void 0,
2104
- inTransitAt: item.in_transit_at ?? void 0,
2105
- deliveredAt: item.delivered_at ?? void 0,
2106
- estimatedDeliveryAt: item.estimated_delivery_at ?? void 0,
2107
- fulfillmentDisplayStatus: item.fulfillment_display_status ? stringToFulfillmentDisplayStatusEnumValue(item.fulfillment_display_status) : void 0,
2108
- trackingUrl: item.tracking_url ?? void 0
2109
- }))
2110
- }
2111
- };
2112
- };
2113
-
2114
- //#endregion
2115
- //#region src/adapters/spiffy/commerce/exceptions/sessionExceptions.ts
2116
- var SessionRestartRequired = class extends Error {
2117
- constructor() {
2118
- super("Session restart required");
2119
- this.name = "SessionRestartRequired";
2120
- }
2121
- };
2122
-
2123
- //#endregion
2124
- //#region src/adapters/spiffy/commerce/exceptions/unsupportedProductExceptions.ts
2125
- var UnsupportedProductException = class extends Error {
2126
- constructor() {
2127
- super("Unsupported product");
2128
- this.name = "UnsupportedProduct";
2129
- }
2130
- };
2131
-
2132
- //#endregion
2133
- //#region src/application/models/guards/api/isApiOrganizationConfig.ts
2134
- const isApiOrgAnalyticsConfigAmplitude = (data) => {
2135
- if (data == null || typeof data !== "object") {
2136
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigAmplitude: data is not an object", data);
2137
- return false;
2138
- }
2139
- if (!("session_replay_enabled" in data) || typeof data.session_replay_enabled !== "boolean") {
2140
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigAmplitude: session_replay_enabled is not a boolean", data);
2141
- return false;
2142
- }
2143
- if (!("session_replay_sample_rate" in data) || typeof data.session_replay_sample_rate !== "number") {
2144
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigAmplitude: session_replay_sample_rate is not a number", data);
2145
- return false;
2146
- }
2147
- if (!("tracking_enabled" in data) || typeof data.tracking_enabled !== "boolean") {
2148
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigAmplitude: tracking_enabled is not a boolean", data);
2149
- return false;
2150
- }
2151
- return true;
2152
- };
2153
- const isApiOrgAnalyticsConfigCustomerService = (data) => {
2154
- if (data == null || typeof data !== "object") {
2155
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigCustomerService: data is not an object", data);
2156
- return false;
2157
- }
2158
- if (!("provider" in data) || typeof data.provider !== "string") {
2159
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigCustomerService: provider is not a string", data);
2160
- return false;
2161
- }
2162
- return true;
2163
- };
2164
- const isApiOrgAnalyticsConfigGoogleAnalytics = (data) => {
2165
- if (data == null || typeof data !== "object") {
2166
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigGoogleAnalytics: data is not an object", data);
2167
- return false;
2168
- }
2169
- if (!("measurement_id" in data) || typeof data.measurement_id !== "string") {
2170
- logger_default.logDebug("[spiffy-ai] isApiOrgAnalyticsConfigGoogleAnalytics: measurement_id is not a string", data);
2171
- return false;
2172
- }
2173
- return true;
2174
- };
2175
- /**
2176
- *
2177
- * @param data
2178
- * @returns
2179
- */
2180
- const isApiOrgAnalyticsConfig = (data) => {
2181
- if (data == null || typeof data !== "object") {
2182
- logger_default.logDebug("[spiffy-ai] isOrgAnalyticsConfig: data is not an object", data);
2183
- return false;
2184
- }
2185
- if ("amplitude" in data && !isApiOrgAnalyticsConfigAmplitude(data.amplitude)) {
2186
- logger_default.logDebug("[spiffy-ai] isOrgAnalyticsConfig: amplitude is not an object", data);
2187
- return false;
2188
- }
2189
- if ("customer_service" in data && !isApiOrgAnalyticsConfigCustomerService(data.customer_service)) {
2190
- logger_default.logDebug("[spiffy-ai] isOrgAnalyticsConfig: customer_service is not an object", data);
2191
- return false;
2192
- }
2193
- if ("google_analytics" in data && !isApiOrgAnalyticsConfigGoogleAnalytics(data.google_analytics)) {
2194
- logger_default.logDebug("[spiffy-ai] isOrgAnalyticsConfig: google_analytics is not an object", data);
2195
- return false;
2196
- }
2197
- return true;
2198
- };
2199
- /**
2200
- *
2201
- * @param data
2202
- * @returns
2203
- */
2204
- const isApiOrganizationConfig = (data) => {
2205
- if (data == null || typeof data !== "object") {
2206
- logger_default.logDebug("[spiffy-ai] isOrgConfig: data is not an object", data);
2207
- return false;
2208
- }
2209
- if (!("created_at" in data)) {
2210
- logger_default.logDebug("[spiffy-ai] isOrgConfig: created_at is not defined", data);
2211
- return false;
2212
- }
2213
- if (!("namespace" in data) || typeof data.namespace !== "string") {
2214
- logger_default.logDebug("[spiffy-ai] isOrgConfig: namespace is not a string", data);
2215
- return false;
2216
- }
2217
- if (!("is_latest" in data) || typeof data.is_latest !== "boolean") {
2218
- logger_default.logDebug("[spiffy-ai] isOrgConfig: is_latest is not a boolean", data);
2219
- return false;
2220
- }
2221
- if (!("version" in data) || typeof data.version !== "string") {
2222
- logger_default.logDebug("[spiffy-ai] isOrgConfig: version is not a string", data);
2223
- return false;
2224
- }
2225
- if (!("updated_at" in data)) {
2226
- logger_default.logDebug("[spiffy-ai] isOrgConfig: updated_at is not defined", data);
2227
- return false;
2228
- }
2229
- if (!("config" in data) || typeof data.config !== "object" || !isApiOrgAnalyticsConfig(data.config)) {
2230
- logger_default.logDebug("[spiffy-ai] isOrgConfig: config is not an object", data);
2231
- return false;
2232
- }
2233
- if ("organization_id" in data && typeof data.organization_id !== "string") {
2234
- logger_default.logDebug("[spiffy-ai] isOrgConfig: organization_id is not a string", data);
2235
- return false;
2236
- }
2237
- if ("id" in data && typeof data.id !== "string") {
2238
- logger_default.logDebug("[spiffy-ai] isOrgConfig: id is not a string", data);
2239
- return false;
2240
- }
2241
- return true;
2242
- };
2243
-
2244
- //#endregion
2245
- //#region src/application/models/guards/api/isApiOrgConfigResults.ts
2246
- const isApiOrgConfigExperiment = (data) => {
2247
- if (data == null || typeof data !== "object") {
2248
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigExperiment: data is not an object", void 0, { data });
2249
- return false;
2250
- }
2251
- if ("group" in data && typeof data.group !== "string" && data.group !== void 0) {
2252
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigExperiment: group is not a string or undefined", void 0, { data });
2253
- return false;
2254
- }
2255
- if ("group_name" in data && typeof data.group_name !== "string" && data.group_name !== void 0) {
2256
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigExperiment: group_name is not a string", void 0, { data });
2257
- return false;
2258
- }
2259
- if ("name" in data && typeof data.name !== "string" && data.name !== void 0) {
2260
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigExperiment: name is not a string", void 0, { data });
2261
- return false;
2262
- }
2263
- if ("rule_id" in data && typeof data.rule_id !== "string" && data.rule_id !== void 0) {
2264
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigExperiment: rule_id is not a string", void 0, { data });
2265
- return false;
2266
- }
2267
- if ("value" in data && typeof data.value !== "object" && data.value !== void 0) {
2268
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigExperiment: value is not an object", void 0, { data });
2269
- return false;
2270
- }
2271
- return true;
2272
- };
2273
- const isApiOrgConfigFeatureGate = (data) => {
2274
- if (data == null || typeof data !== "object") {
2275
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigFeatureGate: data is not an object", void 0, { data });
2276
- return false;
2277
- }
2278
- if ("name" in data && typeof data.name !== "string" && data.name !== void 0) {
2279
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigFeatureGate: name is not a string", void 0, { data });
2280
- return false;
2281
- }
2282
- if ("rule_id" in data && typeof data.rule_id !== "string" && data.rule_id !== void 0) {
2283
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigFeatureGate: rule_id is not a string", void 0, { data });
2284
- return false;
2285
- }
2286
- if ("value" in data && typeof data.value !== "boolean" && data.value !== void 0) {
2287
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigFeatureGate: value is not a boolean", void 0, { data });
2288
- return false;
2289
- }
2290
- return true;
2291
- };
2292
- const isApiOrganization = (data) => {
2293
- if (data == null || typeof data !== "object") {
2294
- logger_default.logDebug("[spiffy-ai] isApiOrganization: data is not an object", void 0, { data });
2295
- return false;
2296
- }
2297
- if (!("id" in data) || typeof data.id !== "string") {
2298
- logger_default.logDebug("[spiffy-ai] isApiOrganization: id is not a string", void 0, { data });
2299
- return false;
2300
- }
2301
- if (!("display_name" in data) || typeof data.display_name !== "string") {
2302
- logger_default.logDebug("[spiffy-ai] isApiOrganization: display_name is not a string", void 0, { data });
2303
- return false;
2304
- }
2305
- if (!("domain" in data) || typeof data.domain !== "string") {
2306
- logger_default.logDebug("[spiffy-ai] isApiOrganization: domain is not a string", void 0, { data });
2307
- return false;
2308
- }
2309
- if (!("short_name" in data) || typeof data.short_name !== "string") {
2310
- logger_default.logDebug("[spiffy-ai] isApiOrganization: short_name is not a string", void 0, { data });
2311
- return false;
2312
- }
2313
- if (!("status" in data) || !Object.values(OrganizationStatusEnum).includes(data.status)) {
2314
- logger_default.logDebug("[spiffy-ai] isApiOrganization: status is not a valid OrganizationStatusEnum value", void 0, { data });
2315
- return false;
2316
- }
2317
- if ("created_at" in data && !(data.created_at instanceof Date) && typeof data.created_at !== "string" && data.created_at !== void 0) {
2318
- logger_default.logDebug("[spiffy-ai] isApiOrganization: created_at is not a Date", void 0, { data });
2319
- return false;
2320
- }
2321
- if ("updated_at" in data && !(data.updated_at instanceof Date) && typeof data.updated_at !== "string" && data.updated_at !== void 0) {
2322
- logger_default.logDebug("[spiffy-ai] isApiOrganization: updated_at is not a Date", void 0, { data });
2323
- return false;
2324
- }
2325
- return true;
2326
- };
2327
- const isApiOrgConfigOrganizationSettings = (data) => {
2328
- if (data == null || typeof data !== "object") {
2329
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigOrganizationSettings: data is not an object", void 0, { data });
2330
- return false;
2331
- }
2332
- if (!("org" in data) || !isApiOrganization(data.org)) {
2333
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigOrganizationSettings: org is not an object", void 0, { data });
2334
- return false;
2335
- }
2336
- return true;
2337
- };
2338
- /**
2339
- *
2340
- * @param data
2341
- * @returns
2342
- */
2343
- const isApiOrgConfigResults = (data) => {
2344
- if (data == null || typeof data !== "object") {
2345
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigResults: data is not an object", void 0, { data });
2346
- return false;
2347
- }
2348
- if (!("configs" in data) || !Array.isArray(data.configs) || !data.configs.every((config) => isApiOrganizationConfig(config))) {
2349
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigResults: configs is not an array", void 0, { data });
2350
- return false;
2351
- }
2352
- if ("experiments" in data && data.experiments !== void 0 && (!Array.isArray(data.experiments) || !data.experiments.every((exp) => isApiOrgConfigExperiment(exp)))) {
2353
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigResults: experiments is not an array or contains invalid items", void 0, { data });
2354
- return false;
2355
- }
2356
- if (!("gates" in data) || !Array.isArray(data.gates) || !data.gates.every((gate) => isApiOrgConfigFeatureGate(gate))) {
2357
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigResults: gates is not an array or contains invalid items", void 0, { data });
2358
- return false;
2359
- }
2360
- if (!("org" in data) || !isApiOrgConfigOrganizationSettings(data.org)) {
2361
- logger_default.logDebug("[spiffy-ai] isApiOrgConfigResults: org is not an object or has invalid fields", void 0, { data });
2362
- return false;
2363
- }
2364
- return true;
2365
- };
2366
-
2367
- //#endregion
2368
- //#region src/application/models/validators/validateOrganizationConfig.ts
2369
- const validateOrganizationConfig = (data) => {
2370
- if (!isApiOrganizationConfig(data)) return;
2371
- return {
2372
- id: data.id,
2373
- createdAt: data.created_at.toISOString(),
2374
- namespace: data.namespace,
2375
- organizationId: data.organization_id,
2376
- isLatest: data.is_latest,
2377
- version: data.version,
2378
- updatedAt: data.updated_at.toISOString(),
2379
- config: {
2380
- amplitude: data.config.amplitude ? {
2381
- sessionReplayEnabled: data.config.amplitude.session_replay_enabled,
2382
- sessionReplaySampleRate: data.config.amplitude.session_replay_sample_rate,
2383
- trackingEnabled: data.config.amplitude.tracking_enabled
2384
- } : void 0,
2385
- customerService: data.config.customer_service ? { provider: data.config.customer_service.provider } : void 0,
2386
- googleAnalytics: data.config.google_analytics ? { measurementId: data.config.google_analytics.measurement_id } : void 0
2387
- }
2388
- };
2389
- };
2390
-
2391
- //#endregion
2392
- //#region src/application/models/validators/validateOrgConfigResults.ts
2393
- /**
2394
- *
2395
- * @param data
2396
- * @returns
2397
- */
2398
- const validateOrgConfigResults = (data) => {
2399
- if (!isApiOrgConfigResults(data)) return;
2400
- return {
2401
- configs: data.configs.map((config) => validateOrganizationConfig(config)).filter((config) => config != null),
2402
- experiments: data.experiments.map((experiment) => ({
2403
- group: experiment.group,
2404
- groupName: experiment.group_name,
2405
- name: experiment.name,
2406
- ruleId: experiment.rule_id,
2407
- value: experiment.value
2408
- })),
2409
- gates: data.gates.map((gate) => ({
2410
- groupName: gate.group_name,
2411
- name: gate.name,
2412
- ruleId: gate.rule_id,
2413
- value: gate.value
2414
- })),
2415
- org: {
2416
- org: {
2417
- id: data.org.org.id,
2418
- displayName: data.org.org.display_name,
2419
- domain: data.org.org.domain,
2420
- shortName: data.org.org.short_name,
2421
- status: data.org.org.status,
2422
- createdAt: data.org.org.created_at?.toISOString(),
2423
- updatedAt: data.org.org.updated_at?.toISOString()
2424
- },
2425
- settings: {}
2426
- }
2427
- };
2428
- };
2429
-
2430
- //#endregion
2431
- //#region src/application/service/windowDataLayerService.ts
2432
- var WindowDataLayerService = class WindowDataLayerService {
2433
- constructor(gaConfig) {
2434
- this.gaConfig = gaConfig;
2435
- this.dataLayer = window.dataLayer;
2436
- this.originalDataLayerPush = this.dataLayer?.push;
2437
- this.merchantGoogleMeasurementId = this.gaConfig.measurementId || "default";
2438
- }
2439
- /**
2440
- * Pushes data to the dataLayer
2441
- * @param data
2442
- * data has the shape: { event: 'event_name', ... }
2443
- * Example:
2444
- * {
2445
- * "event": "add_to_cart",
2446
- * "currency": "USD",
2447
- * "value": 30.03,
2448
- * "items": [
2449
- * {
2450
- * "item_id": "SKU_12345",
2451
- * "item_name": "Stan and Friends Tee",
2452
- * "affiliation": "Google Merchandise Store",
2453
- * "coupon": "SUMMER_FUN",
2454
- * "discount": 2.22,
2455
- * "index": 0,
2456
- * "item_brand": "Google",
2457
- * "item_category": "Apparel",
2458
- * "item_category2": "Adult",
2459
- * "item_category3": "Shirts",
2460
- * "item_category4": "Crew",
2461
- * "item_category5": "Short sleeve",
2462
- * "item_list_id": "related_products",
2463
- * "item_list_name": "Related Products",
2464
- * "item_variant": "green",
2465
- * "location_id": "ChIJIQBpAG2ahYAR_6128GcTUEo",
2466
- * "price": 10.01,
2467
- * "quantity": 3
2468
- * }
2469
- * ]
2470
- * }
2471
- */
2472
- push(data) {
2473
- this.dataLayer?.push(data);
2474
- }
2475
- static isDataLayerAvailable() {
2476
- const windowDataLayer = window.dataLayer;
2477
- if (windowDataLayer && windowDataLayer.push) return true;
2478
- logger_default.logDebug("[spiffy-ai] DataLayerEventsListener dataLayer not available");
2479
- return false;
2480
- }
2481
- static tryFlattenArguments(args) {
2482
- function isArguments(obj) {
2483
- return obj !== void 0 && Object.prototype.toString.call(obj) === "[object Arguments]";
2484
- }
2485
- try {
2486
- const all_arguments = [];
2487
- if (args.length > 0) for (let i = 0; i < args.length; i++) {
2488
- const arg = args[i];
2489
- if (isArguments(arg)) {
2490
- const flattened = WindowDataLayerService.tryFlattenArguments(arg);
2491
- all_arguments.push(...flattened);
2492
- } else all_arguments.push(arguments[i]);
2493
- }
2494
- return all_arguments;
2495
- } catch {
2496
- return args;
2497
- }
2498
- }
2499
- wrapWithProxyMethod(methodName, callback) {
2500
- if (!this.dataLayer) {
2501
- logger_default.logWarn("DataLayerEventsListener dataLayer not available", void 0);
2502
- return;
2503
- }
2504
- const originalMethod = this.dataLayer[methodName];
2505
- this.dataLayer[methodName] = function() {
2506
- try {
2507
- callback.apply(this, arguments);
2508
- } catch (e) {
2509
- logger_default.logError(`Error in dataLayer.${methodName}: `, e);
2510
- } finally {
2511
- originalMethod.apply(this, arguments);
2512
- }
2513
- };
2514
- }
2515
- static getSingletonInstanceOf(gaConfig) {
2516
- if (!WindowDataLayerService.instance) WindowDataLayerService.instance = new WindowDataLayerService(gaConfig);
2517
- return WindowDataLayerService.instance;
2518
- }
2519
- sendToGoogleAnalyticsCircularEventsSafe(eventName, eventProps) {
2520
- const This = this;
2521
- function doesEventExistInDataLayer(eventName$1) {
2522
- return This.dataLayer?.find((event) => event.event === eventName$1);
2523
- }
2524
- if (doesEventExistInDataLayer(eventName)) {
2525
- logger_default.logDebug(`[spiffy-ai] Event ${eventName} already exists in dataLayer. Skipping Google Analytics event.`);
2526
- return;
2527
- }
2528
- function gtag() {
2529
- if (This.originalDataLayerPush) This.originalDataLayerPush(arguments);
2530
- else logger_default.logDebug("No originalDataLayerPush found - no metrics being logged");
2531
- }
2532
- gtag("event", eventName, {
2533
- event: eventName,
2534
- send_to: this.merchantGoogleMeasurementId,
2535
- ...eventProps
2536
- });
2537
- }
2538
- static {
2539
- this.getGoogleAnalyticsClientId = () => {
2540
- try {
2541
- const gaCookie = document.cookie.split(";").find((c) => c.trim().startsWith("_ga="));
2542
- if (!gaCookie) {
2543
- logger_default.logWarn("[spiffy-ai] No GA cookie found", void 0);
2544
- return;
2545
- }
2546
- return gaCookie.split(".").slice(2).join(".");
2547
- } catch (error) {
2548
- logger_default.logError("Error getting GA client ID:", error);
2549
- return;
2550
- }
2551
- };
2552
- }
2553
- };
2554
-
2555
- //#endregion
2556
- //#region src/application/service/userIdentityService.ts
2557
- const getUserAgentDetails = () => {
2558
- const result = new UAParser().getResult();
2559
- return {
2560
- os: result?.os?.name,
2561
- osVersion: result?.os?.version,
2562
- deviceBrand: result?.device?.vendor,
2563
- deviceManufacturer: result?.device?.vendor,
2564
- deviceModel: result?.device?.model,
2565
- browser: result?.browser?.name,
2566
- browserVersion: result?.browser?.version,
2567
- userAgent: result?.ua
2568
- };
2569
- };
2570
- var UserIdentityService = class UserIdentityService {
2571
- static {
2572
- this.USER_ID_OVERRIDE_KEY = "v1-spiffy-user-id-override";
2573
- }
2574
- static {
2575
- this.USER_ID_DEFAULT_KEY = "v1-spiffy-user-id-default";
2576
- }
2577
- static async identifyUser() {
2578
- try {
2579
- const cdpUserId = WindowDataLayerService.getGoogleAnalyticsClientId();
2580
- const userId = UserIdentityService.getUserIdOrDefault();
2581
- const userAgentDetails = getUserAgentDetails();
2582
- if (!cdpUserId) {
2583
- logger_default.logWarn("[spiffy-ai] No GA Client ID found, skipping identifyUser", void 0);
2584
- return;
2585
- }
2586
- await api_default.identifyUser(userId, cdpUserId, userAgentDetails);
2587
- } catch (error) {
2588
- logger_default.logError("[spiffy-ai] Error identifying user", error);
2589
- }
2590
- }
2591
- static getUserIdOrDefault() {
2592
- const userIdOverride = UserIdentityService.getUserIdOverrideFromLocalStorage();
2593
- if (userIdOverride) return userIdOverride;
2594
- const defaultUserId = UserIdentityService.getUserIdDefaultFromLocalStorage();
2595
- if (defaultUserId) return defaultUserId;
2596
- return this.setUserIdDefaultInLocalStorage(`spiffy-user-id-${v4()}`);
2597
- }
2598
- static getUserIdOverrideFromLocalStorage() {
2599
- return LocalStorageService.getLocalStorage()?.getItem(UserIdentityService.USER_ID_OVERRIDE_KEY) ?? void 0;
2600
- }
2601
- static getUserIdDefaultFromLocalStorage() {
2602
- return LocalStorageService.getLocalStorage()?.getItem(UserIdentityService.USER_ID_DEFAULT_KEY) ?? void 0;
2603
- }
2604
- static setUserIdDefaultInLocalStorage(userId) {
2605
- logger_default.logInfo(`setUserIdDefaultInLocalStorage - Setting user_id=${userId}`);
2606
- LocalStorageService.getLocalStorage()?.setItem(UserIdentityService.USER_ID_DEFAULT_KEY, userId);
2607
- window.dispatchEvent(new StorageEvent("storage", {
2608
- key: UserIdentityService.USER_ID_DEFAULT_KEY,
2609
- newValue: userId
2610
- }));
2611
- return userId;
2612
- }
2613
- static setUserIdOverrideInLocalStorage(userId) {
2614
- logger_default.logInfo(`setUserIdOverrideInLocalStorage - Setting user_id=${userId}`);
2615
- LocalStorageService.getLocalStorage()?.setItem(UserIdentityService.USER_ID_OVERRIDE_KEY, userId);
2616
- window.dispatchEvent(new StorageEvent("storage", {
2617
- key: UserIdentityService.USER_ID_OVERRIDE_KEY,
2618
- newValue: userId
2619
- }));
2620
- return userId;
2621
- }
2622
- static clearUserIdOverrideInLocalStorage() {
2623
- logger_default.logInfo(`clearUserIdOverrideInLocalStorage - Clearing user_id`);
2624
- LocalStorageService.getLocalStorage()?.removeItem(UserIdentityService.USER_ID_OVERRIDE_KEY);
2625
- window.dispatchEvent(new StorageEvent("storage", {
2626
- key: UserIdentityService.USER_ID_OVERRIDE_KEY,
2627
- newValue: void 0
2628
- }));
2629
- }
2630
- };
2631
-
2632
- //#endregion
2633
- //#region src/atoms/app/variant.ts
2634
- const internalStorageUrlResolverAtom = atomWithStorage("spiffy-url-resolver", void 0, sessionStorageUtil, { getOnInit: true });
2635
- const urlResolverAtom = atom((get) => {
2636
- const maybeUrlResolver = get(internalStorageUrlResolverAtom);
2637
- if (maybeUrlResolver == null) return {};
2638
- return JSON.parse(maybeUrlResolver);
2639
- }, (get, set, value) => {
2640
- const newCache = {
2641
- ...get(urlResolverAtom),
2642
- [value.url]: value.response
2643
- };
2644
- set(internalStorageUrlResolverAtom, JSON.stringify(newCache));
2645
- });
2646
- const internalStorageSupportedEventAtom = atomWithStorage("spiffy-supported-event", void 0, sessionStorageUtil, { getOnInit: true });
2647
- const internalSupportedEventAtom = atom(void 0);
2648
- const supportedEventAtom = atom((get) => {
2649
- const maybeSupportedEvent = get(internalStorageSupportedEventAtom);
2650
- if (maybeSupportedEvent == null) return;
2651
- return JSON.parse(maybeSupportedEvent);
2652
- }, (get, set, value) => {
2653
- if (value == null) {
2654
- set(internalStorageSupportedEventAtom, void 0);
2655
- set(internalSupportedEventAtom, void 0);
2656
- return;
2657
- }
2658
- const featureFlagService = get(featureFlagServiceAtom);
2659
- const variantCategory = get(internalSupportedEventAtom)?.category;
2660
- const shortName = get(orgShortNameAtom);
2661
- if (!featureFlagService.isFeatureGateEnabled(FeatureGates.IsNonShapewearEnabled) && variantCategory && variantCategory !== SupportedEventProductCategory.Shapewear && (shortName === OrgShortName.Spanx || shortName === OrgShortName.SpanxStaging)) {
2662
- const modifiedSupportedEvent = {
2663
- supported: false,
2664
- ready: value.ready,
2665
- category: value.category,
2666
- numberOfReviews: value.numberOfReviews,
2667
- collections: value.collections,
2668
- top_category: value.top_category,
2669
- merchant_tags: value.merchant_tags
2670
- };
2671
- set(internalSupportedEventAtom, modifiedSupportedEvent);
2672
- set(internalStorageSupportedEventAtom, JSON.stringify(modifiedSupportedEvent));
2673
- return;
2674
- }
2675
- set(internalSupportedEventAtom, value);
2676
- set(internalStorageSupportedEventAtom, JSON.stringify(value));
2677
- });
2678
- const internalVariantIdAtom = atom();
2679
- const internalProductIdAtom = atom();
2680
- const internalParentProductIdAtom = atom();
2681
- const internalProductUrlAtom = atom();
2682
- const internalPlpIdAtom = atom();
2683
- const internalUrlAtom = atom();
2684
- const internalPageVisitCategoryAtom = atom();
2685
- const internalVariantAtom = atom("pdp");
2686
- const variantIdAtom = atom((get) => get(internalVariantIdAtom));
2687
- const productIdAtom = atom((get) => get(internalProductIdAtom));
2688
- const parentProductIdAtom = atom((get) => get(internalParentProductIdAtom));
2689
- const productUrlAtom = atom((get) => get(internalProductUrlAtom));
2690
- const plpIdAtom = atom((get) => get(internalPlpIdAtom));
2691
- const urlAtom = atom((get) => get(internalUrlAtom));
2692
- const pageVisitCategoryAtom = atom((get) => get(internalPageVisitCategoryAtom));
2693
- const variantAtom = atom((get) => get(internalVariantAtom));
2694
- const hasParsedVariantInfoAtom = atom(false);
2695
- const variantInfoAtom = atom((get) => {
2696
- const variant = get(variantAtom);
2697
- if (variant === "pdp") return {
2698
- variantId: get(variantIdAtom),
2699
- variant,
2700
- productId: get(productIdAtom),
2701
- parentProductId: get(parentProductIdAtom),
2702
- url: get(urlAtom)
2703
- };
2704
- if (variant === "plp") return {
2705
- variantId: get(variantIdAtom),
2706
- variant,
2707
- plpId: get(plpIdAtom),
2708
- url: get(urlAtom)
2709
- };
2710
- if (variant === "page_visit") return {
2711
- variantId: get(variantIdAtom),
2712
- variant,
2713
- url: get(urlAtom),
2714
- pageVisitCategory: get(pageVisitCategoryAtom)
2715
- };
2716
- throw new Error("Invalid variantInfo details");
2717
- }, (_, set, newVariant) => {
2718
- set(internalVariantAtom, newVariant.variant);
2719
- set(internalVariantIdAtom, newVariant.variantId);
2720
- if (newVariant.variant === "pdp") {
2721
- set(internalProductIdAtom, newVariant.productId);
2722
- set(internalParentProductIdAtom, newVariant.parentProductId);
2723
- set(internalUrlAtom, newVariant.url);
2724
- }
2725
- if (newVariant.variant === "plp") {
2726
- set(internalPlpIdAtom, newVariant.plpId);
2727
- set(internalUrlAtom, newVariant.url);
2728
- }
2729
- if (newVariant.variant === "page_visit") {
2730
- set(internalUrlAtom, newVariant.url);
2731
- set(internalPageVisitCategoryAtom, newVariant.pageVisitCategory);
2732
- }
2733
- });
2734
-
2735
- //#endregion
2736
- //#region src/atoms/app/index.ts
2737
- const internalUserIdAtom = atom(void 0);
2738
- const userIdAtom = atom((get) => {
2739
- const maybeUserId = get(internalUserIdAtom);
2740
- if (maybeUserId) return maybeUserId;
2741
- return UserIdentityService.getUserIdOrDefault();
2742
- }, (_, set, value) => {
2743
- set(internalUserIdAtom, value);
2744
- });
2745
- const appSourceAtom = atom((get) => get(sourceAtom) ?? ContextSourceEnum.App);
2746
- const envAtom = atom(ContextEnvEnum.Dev);
2747
- const chatIdAtom = atomWithStorage("v1-spiffy-chat-session-id", v4(), void 0, { getOnInit: true });
2748
- const appDetailsAtom = atom((get) => ({
2749
- orgId: get(orgIdAtom),
2750
- orgShortName: get(orgShortNameAtom) ?? "spiffy-ai",
2751
- chatId: get(chatIdAtom),
2752
- userId: get(userIdAtom),
2753
- source: get(appSourceAtom),
2754
- env: get(envAtom),
2755
- variantInfo: get(variantInfoAtom)
2756
- }));
2757
-
2758
- //#endregion
2759
- //#region src/adapters/spiffy/commerce/api.ts
2760
- async function errorResponseBody(error) {
2761
- try {
2762
- return await error.response.json();
2763
- } catch {
2764
- return {};
2765
- }
2766
- }
2767
- async function throwSessionRestartRequiredIf(errorMsg, error) {
2768
- if (!(error instanceof ResponseError)) {
2769
- logger_default.logInfo(errorMsg, error);
2770
- throw error;
2771
- }
2772
- const errorResponse = await errorResponseBody(error);
2773
- if (errorResponse?.message?.toLowerCase() === "unsupported product" || errorResponse?.app_code?.toUpperCase() === "PRODUCT_NOT_FOUND") throw new UnsupportedProductException();
2774
- else if (errorResponse?.app_code?.toUpperCase() === "RESTART_SESSION" || errorResponse?.sub_code?.toUpperCase() === "NOT_FOUND") {
2775
- logger_default.logInfo("Session does not exist. Re-start session", error, error.response, errorResponse);
2776
- throw new SessionRestartRequired();
2777
- }
2778
- logger_default.logInfo(errorMsg, error);
2779
- throw error;
2780
- }
2781
- var CommerceApiClient = class CommerceApiClient {
2782
- static {
2783
- this.getInstance = () => {
2784
- if (!CommerceApiClient.instance) {
2785
- const apiKey = getAtomStore().get(apiKeyAtom);
2786
- CommerceApiClient.instance = new CommerceApiClient(apiKey);
2787
- }
2788
- return CommerceApiClient.instance;
2789
- };
2790
- }
2791
- constructor(apiKey, basePath) {
2792
- this.suggestionsAbortController = new AbortController();
2793
- this.responsesAbortController = new AbortController();
2794
- const { baseUrl } = useEnviveConfig();
2795
- const config = new Configuration({
2796
- accessToken: apiKey,
2797
- basePath: basePath || baseUrl,
2798
- headers: {
2799
- "Content-Type": "application/json",
2800
- Accept: "application/json"
2801
- }
2802
- });
2803
- this.defaultApi = new DefaultApi(config);
2804
- this.inferenceApi = new InferenceApi(config);
2805
- this.customerServiceApi = new CustomerServiceApi(config);
2806
- }
2807
- static {
2808
- this.resolveUrl = async (url) => {
2809
- const atomStore = getAtomStore();
2810
- const appDetails = atomStore.get(appDetailsAtom);
2811
- const featureFlagService = atomStore.get(featureFlagServiceAtom);
2812
- const context = {
2813
- user_id: appDetails.userId,
2814
- org_id: appDetails.orgId,
2815
- org_short_name: appDetails.orgShortName,
2816
- chat_id: appDetails.chatId,
2817
- source: appDetails.source,
2818
- env: appDetails.env
2819
- };
2820
- const featureGates = featureFlagService.getFeatureFlags();
2821
- const urlResolvingRequest = {
2822
- url,
2823
- context,
2824
- feature_gates: featureGates
2825
- };
2826
- return await (await CommerceApiClient.getInstance().inferenceApi.v1UrlResolvingPostRaw({ UrlResolvingRequest: urlResolvingRequest })).raw.json();
2827
- };
2828
- }
2829
- static {
2830
- this.reportSession = async (reportRequest) => {
2831
- await CommerceApiClient.getInstance().defaultApi.v1ChatsReportSessionIdPost({ ReportSessionRequest: reportRequest });
2832
- };
2833
- }
2834
- static {
2835
- this.getNextResponses = async (payload) => {
2836
- try {
2837
- return (await CommerceApiClient.getInstance().inferenceApi.v1NextResponsesPost({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) })).map((resp) => validateResponse(resp)).map((resp) => messageFromResponse(resp)).filter((m) => m != null);
2838
- } catch (err) {
2839
- logger_default.logInfo("Failed to get next responses", err, {
2840
- payloadContext: payload?.context,
2841
- userEvents: payload?.userEvents
2842
- });
2843
- await throwSessionRestartRequiredIf("Failed to get next responses", err);
2844
- return [];
2845
- }
2846
- };
2847
- }
2848
- static {
2849
- this.getNextResponseStreaming = (payload) => {
2850
- async function* generate(inferenceApi, abortController) {
2851
- try {
2852
- const response = await inferenceApi.v1NextResponsesPostRaw({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) }, { signal: abortController.signal });
2853
- if (!response.raw.body) {
2854
- logger_default.logError("[spiffy-ai] No body in the streamed response", void 0, { response: response.raw });
2855
- return;
2856
- }
2857
- const reader = response.raw.body.getReader();
2858
- const decoder = new TextDecoder("utf-8");
2859
- let partial = "";
2860
- const safeParse = (line) => {
2861
- try {
2862
- return JSON.parse(line);
2863
- } catch (err) {
2864
- logger_default.logError("[spiffy-ai] Error parsing streamed line", err, {
2865
- line,
2866
- partial
2867
- });
2868
- partial = line;
2869
- return partial;
2870
- }
2871
- };
2872
- const processChunk = (chunk) => {
2873
- return `${partial}${chunk}`.split("\n").map((line) => line.replace(/^data: /, "").trim()).filter((line) => line !== "" && line !== "[DONE]").map(safeParse).filter((v) => v);
2874
- };
2875
- while (true) {
2876
- const { done, value } = await reader.read();
2877
- if (done) break;
2878
- const chunk = decoder.decode(value);
2879
- const parsedLines = processChunk(chunk);
2880
- for (const parsedLine of parsedLines) {
2881
- const validatedResponse = validateResponse(parsedLine);
2882
- if (validatedResponse) yield validatedResponse;
2883
- }
2884
- }
2885
- } catch (error) {
2886
- logger_default.logError("[spiffy-ai] Failed to get next streaming responses", error, {
2887
- payloadContext: payload?.context,
2888
- userEvents: payload?.userEvents
2889
- });
2890
- await throwSessionRestartRequiredIf("Failed to get next streaming responses", error);
2891
- }
2892
- }
2893
- CommerceApiClient.getInstance().responsesAbortController.abort();
2894
- CommerceApiClient.getInstance().responsesAbortController = new AbortController();
2895
- return generate(CommerceApiClient.getInstance().inferenceApi, CommerceApiClient.getInstance().responsesAbortController);
2896
- };
2897
- }
2898
- static {
2899
- this.getNextSuggestions = async (payload) => {
2900
- try {
2901
- CommerceApiClient.getInstance().suggestionsAbortController.abort();
2902
- CommerceApiClient.getInstance().suggestionsAbortController = new AbortController();
2903
- return (await CommerceApiClient.getInstance().inferenceApi.v1NextSuggestionsPost({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) }, { signal: CommerceApiClient.getInstance().suggestionsAbortController.signal })).map((resp) => validateSuggestion(resp)).filter((suggestion) => suggestion != null);
2904
- } catch (error) {
2905
- logger_default.logInfo("Failed to get suggestions", error, {
2906
- payloadContext: payload?.context,
2907
- userEvents: payload?.userEvents
2908
- });
2909
- await throwSessionRestartRequiredIf("Failed to get suggestions", error);
2910
- return [];
2911
- }
2912
- };
2913
- }
2914
- static {
2915
- this.getResponses = async (orgId, chatId, userId) => {
2916
- let data = {
2917
- responses: [],
2918
- suggestions: [],
2919
- user_events: []
2920
- };
2921
- const request = {
2922
- org_id: orgId,
2923
- chat_id: chatId,
2924
- user_id: userId
2925
- };
2926
- try {
2927
- data = await CommerceApiClient.getInstance().defaultApi.v1GetSessionMessages(request);
2928
- } catch (error) {
2929
- await throwSessionRestartRequiredIf("Failed to get chat responses", error);
2930
- }
2931
- const responses = data?.responses?.map((turn) => turn.map((response) => validateResponse(response)).filter((response) => response != null));
2932
- const suggestions = data?.suggestions.map((suggestion) => validateSuggestion(suggestion)).filter((suggestion) => suggestion != null);
2933
- const userEvents = data?.user_events.map((event) => validateUserEvent(event)).filter((event) => event != null);
2934
- const formSubmittedUserEventsFormIds = userEvents.filter((event) => event.category === UserEventCategory$1.FormSubmitted).map((event) => event.attributes.formResponseId);
2935
- const assistantMessages = responses.map((turn) => turn.filter((response) => !(response.category === ResponseCategory.Form && formSubmittedUserEventsFormIds.includes(response.id))).map((response) => messageFromResponse(response)).filter((message) => message != null)).filter((turn) => turn.length > 0);
2936
- const userMessages = userEvents.map((event) => {
2937
- if ([UserEventCategory$1.QueryTyped, UserEventCategory$1.Search].includes(event.category)) return [messageFromQueryEvent(event)];
2938
- if (event.category === UserEventCategory$1.SuggestionClicked) return [messageFromSuggestionEvent(event, suggestions)];
2939
- if (event.category === UserEventCategory$1.FormSubmitted) {
2940
- const formResponse = responses.flat().find((response) => response.id === event.attributes.formResponseId && event.attributes.formType !== FormType.Escalation);
2941
- if (formResponse && formResponse.category === ResponseCategory.Form) return [messageFromFormSubmittedEvent(event, formResponse.attributes)];
2942
- }
2943
- return [];
2944
- }).filter((message) => message.length > 0);
2945
- const sortedMessages = [...assistantMessages, ...userMessages].sort((a, b) => new Date(a[0].createdAt).getTime() - new Date(b[0].createdAt).getTime());
2946
- return {
2947
- responses,
2948
- userEvents,
2949
- suggestions,
2950
- messages: sortedMessages
2951
- };
2952
- };
2953
- }
2954
- static {
2955
- this.isSupportedEvent = async (payload) => {
2956
- try {
2957
- const httpResponseText = await (await CommerceApiClient.getInstance().inferenceApi.v1SupportedEventPostRaw({ SupportedEventRequest: coreSupportedEventRequestToApiRequest(payload) })).raw.text();
2958
- const httpResponseJson = JSON.parse(httpResponseText);
2959
- return {
2960
- ...httpResponseJson,
2961
- numberOfReviews: httpResponseJson.num_of_reviews,
2962
- merchant_tags: httpResponseJson.merchant_tags || []
2963
- };
2964
- } catch (err) {
2965
- logger_default.logError("Failed to get response for v1SupportedEventPost", { err });
2966
- return {
2967
- supported: false,
2968
- ready: false,
2969
- category: void 0,
2970
- collections: [],
2971
- numberOfReviews: void 0,
2972
- top_category: void 0,
2973
- merchant_tags: []
2974
- };
2975
- }
2976
- };
2977
- }
2978
- static {
2979
- this.identifyUser = async (spiffyUserId, merchantUserId, uaDetails) => {
2980
- try {
2981
- await CommerceApiClient.getInstance().defaultApi.v1AnalyticsIdentifyPost({ AnalyticsIdentifyRequest: {
2982
- user_id: spiffyUserId,
2983
- os_name: uaDetails.os,
2984
- os_version: uaDetails.osVersion,
2985
- platform: uaDetails.os,
2986
- device_id: uaDetails.deviceModel,
2987
- device_brand: uaDetails.deviceBrand,
2988
- device_manufacturer: uaDetails.deviceManufacturer,
2989
- device_model: uaDetails.deviceModel,
2990
- user_properties: {
2991
- cdp_user_id: merchantUserId,
2992
- browser: uaDetails.browser,
2993
- browser_version: uaDetails.browserVersion,
2994
- user_agent: uaDetails.userAgent
2995
- }
2996
- } });
2997
- } catch (err) {
2998
- logger_default.logError("Failed to identify user", err);
2999
- }
3000
- };
3001
- }
3002
- static {
3003
- this.mapContextSourceToV1OrgConfigGetSource = (source) => {
3004
- if (source === void 0) return void 0;
3005
- switch (source) {
3006
- case ContextSourceEnum.Fork: return V1OrgConfigGetSourceEnum.Fork;
3007
- case ContextSourceEnum.Playground: return V1OrgConfigGetSourceEnum.Playground;
3008
- case ContextSourceEnum.App: return V1OrgConfigGetSourceEnum.App;
3009
- case ContextSourceEnum.Test: return V1OrgConfigGetSourceEnum.Test;
3010
- default: return source;
3011
- }
3012
- };
3013
- }
3014
- static {
3015
- this.getOrgConfig = async (user_id) => {
3016
- try {
3017
- const { reactAppName } = useEnviveConfig();
3018
- const request = {
3019
- namespace: reactAppName,
3020
- user_id,
3021
- source: this.mapContextSourceToV1OrgConfigGetSource(EnvironmentService.getContextSource()),
3022
- include_experiments: Object.values(ProductExperiment),
3023
- include_feature_gates: Object.values(FeatureGates)
3024
- };
3025
- const response = await CommerceApiClient.getInstance().defaultApi.v1OrgConfigGet(request);
3026
- return validateOrgConfigResults(response);
3027
- } catch (err) {
3028
- logger_default.logError(`Failed to get org config`, err, { err });
3029
- return;
3030
- }
3031
- };
3032
- }
3033
- static {
3034
- this.addNoteToLatestConversation = async (spiffyUserId, email, customerServiceProvider) => {
3035
- logger_default.logInfo(`addNoteToLatestConversation - user_id=${spiffyUserId} email=${email} customer_service_provider=${customerServiceProvider}`);
3036
- try {
3037
- await CommerceApiClient.getInstance().customerServiceApi.v1CustserviceAddNoteToLatestConversationPost({ AddNoteToLatestConversationRequest: {
3038
- spiffy_user_id: spiffyUserId,
3039
- email,
3040
- customer_service_provider: customerServiceProvider
3041
- } });
3042
- } catch (err) {
3043
- logger_default.logError("Failed to add note to latest conversation", { err });
3044
- }
3045
- };
3046
- }
3047
- static {
3048
- this.getCustomerServiceApi = () => CommerceApiClient.getInstance().customerServiceApi;
3049
- }
3050
- };
3051
- var api_default = CommerceApiClient;
3052
-
3053
- //#endregion
3054
- //#region src/application/service/sessionStorageService.ts
3055
- var SessionStorageService = class {
3056
- static setItem(key, value) {
3057
- sessionStorage.setItem(key, value);
3058
- window.dispatchEvent(new StorageEvent("storage", {
3059
- key,
3060
- newValue: value
3061
- }));
3062
- }
3063
- static getItem(key) {
3064
- return sessionStorage.getItem(key);
3065
- }
3066
- static getSessionStorage() {
3067
- const ls = window?.sessionStorage;
3068
- if (!ls) logger_default.logError("sessionStorage is not available", void 0);
3069
- return ls;
3070
- }
3071
- };
3072
-
3073
- //#endregion
3074
- //#region src/application/service/featureFlagService.ts
3075
- const FEATURE_FLAGS_STORAGE_KEY = "spiffy-feature-flags";
3076
- var FeatureFlagService = class {
3077
- constructor(featureGates) {
3078
- this.featureGates = featureGates;
3079
- this.getQueryParamFeatureGateOverrides = (featureGate) => {
3080
- const urlObj = new URL(window.location.href);
3081
- const params = new URLSearchParams(urlObj.search);
3082
- const value = Object.fromEntries(params.entries())[featureGate];
3083
- if (value != null) return value === "true";
3084
- };
3085
- this.getWindowFeatureGateOverrides = (featureGate) => {
3086
- const value = window._spiffy?.featureOverrides?.[String(featureGate)];
3087
- if (value != null) return value;
3088
- };
3089
- this.getStoredFeatureGateOverrides = (featureGate) => {
3090
- const featureFlags = SessionStorageService.getItem(FEATURE_FLAGS_STORAGE_KEY);
3091
- if (featureFlags) try {
3092
- return JSON.parse(featureFlags)[featureGate];
3093
- } catch (err) {
3094
- logger_default.logError("[spiffy-ai] getStoredFeatureGateOverrides: error parsing feature flags", err);
3095
- }
3096
- };
3097
- }
3098
- persistFeatureGateOverrides() {
3099
- const featureFlags = Object.values(FeatureGates).map((featureGate) => ({ [featureGate]: this.getFeatureFlagOverride(featureGate) })).filter((_, val) => val !== void 0).reduce((acc, curr) => ({
3100
- ...acc,
3101
- ...curr
3102
- }), {});
3103
- SessionStorageService.setItem(FEATURE_FLAGS_STORAGE_KEY, JSON.stringify(featureFlags));
3104
- }
3105
- getFeatureFlagOverride(featureGate) {
3106
- const queryOverride = this.getQueryParamFeatureGateOverrides(featureGate);
3107
- if (queryOverride != null) {
3108
- logger_default.logDebug(`[spiffy-ai] isFeatureGateEnabled featureGate:${featureGate} overridden by URL param. New value: ${queryOverride}`);
3109
- return queryOverride;
3110
- }
3111
- const windowOverride = this.getWindowFeatureGateOverrides(featureGate);
3112
- if (windowOverride != null) {
3113
- logger_default.logDebug(`[spiffy-ai] isFeatureGateEnabled featureGate:${featureGate} overridden by window param. New value: ${windowOverride}`);
3114
- return windowOverride;
3115
- }
3116
- const storedOverride = this.getStoredFeatureGateOverrides(featureGate);
3117
- if (storedOverride != null) {
3118
- logger_default.logDebug(`[spiffy-ai] isFeatureGateEnabled featureGate:${featureGate} overridden by stored value. New value: ${storedOverride}`);
3119
- return storedOverride;
3120
- }
3121
- }
3122
- isFeatureGateEnabled(featureGate) {
3123
- const gateValue = this.featureGates.find((gate) => gate.name === featureGate);
3124
- const featureFlagOverride = this.getFeatureFlagOverride(featureGate);
3125
- if (featureFlagOverride !== void 0) return featureFlagOverride;
3126
- if (gateValue == null || gateValue.value == null) {
3127
- logger_default.logDebug(`[spiffy-ai] isFeatureGateEnabled featureGate:${featureGate} value is undefined - returning false`);
3128
- return false;
3129
- }
3130
- return gateValue.value;
3131
- }
3132
- isClientSessionEnabled() {
3133
- const gates = this.featureGates;
3134
- return gates == null || gates?.filter((gate) => gate.name === FeatureGates.IsClientSessionEnabled && gate.value === true).length > 0;
3135
- }
3136
- getFeatureFlags() {
3137
- return Object.fromEntries(Object.values(FeatureGates).map((featureGate) => [featureGate, this.isFeatureGateEnabled(featureGate)]));
3138
- }
3139
- };
3140
-
3141
- //#endregion
3142
- //#region src/atoms/org/orgAnalyticsConfig.ts
3143
- const internalOrgAnalyticsConfigAtom = atom(void 0);
3144
- const orgAnalyticsConfigAtom = atom((get) => get(internalOrgAnalyticsConfigAtom), (_, set, value) => {
3145
- set(internalOrgAnalyticsConfigAtom, value);
3146
- });
3147
- const orgAnalyticsAmplitudeConfigAtom = atom((get) => get(orgAnalyticsConfigAtom)?.amplitude);
3148
- const orgAnalyticsCustomerServiceConfigAtom = atom((get) => get(orgAnalyticsConfigAtom)?.customerService);
3149
- const orgAnalyticsGoogleAnalyticsConfigAtom = atom((get) => get(orgAnalyticsConfigAtom)?.googleAnalytics);
3150
-
3151
- //#endregion
3152
- //#region src/atoms/org/graphqlConfig.ts
3153
- const internalGraphQLColorsConfigAtom = atom(void 0);
3154
- const internalGraphQLFrontendConfigAtom = atom(void 0);
3155
- const colorsConfigAtom = atom(async (get) => {
3156
- const colors = get(internalGraphQLColorsConfigAtom);
3157
- return {
3158
- ...(await getOrgInfo(get(orgShortNameAtom))).orgColors(),
3159
- ...colors
3160
- };
3161
- }, (_, set, value) => {
3162
- set(internalGraphQLColorsConfigAtom, value);
3163
- });
3164
- const frontendConfigAtom = atom((get) => get(internalGraphQLFrontendConfigAtom), (_, set, value) => {
3165
- set(internalGraphQLFrontendConfigAtom, value);
3166
- });
3167
-
3168
- //#endregion
3169
- //#region src/atoms/org/orgUIConfig.ts
3170
- const getCustomerServiceIntegrationMode = ({ integrationMode, isNewFeatureEnabled }) => {
3171
- if (integrationMode !== CustomerServiceIntegrationMode.full) return integrationMode;
3172
- return isNewFeatureEnabled ? integrationMode : CustomerServiceIntegrationMode.simple;
3173
- };
3174
- const internalOrgUIConfigAtom = atom(void 0);
3175
- const orgUIConfigAtom = atom((get) => {
3176
- const orgUIConfig = get(internalOrgUIConfigAtom);
3177
- if (orgUIConfig) return orgUIConfig;
3178
- throw new Error("OrgUIConfig is referenced before it is set");
3179
- }, (_, set, value) => {
3180
- set(internalOrgUIConfigAtom, value);
3181
- });
3182
- const getOrgUIConfig = async (graphqlOrgUIConfig, graphqlMerchantOverrideCss) => {
3183
- const atomStore = getAtomStore();
3184
- const orgShortName = atomStore.get(orgShortNameAtom);
3185
- const localOrgUIConfig = (await getOrgInfo(orgShortName)).orgUIConfig() ?? {};
3186
- const featureFlagService = atomStore.get(featureFlagServiceAtom);
3187
- const isNewFeatureEnabled = featureFlagService.isFeatureGateEnabled(FeatureGates.IsNewFeatureEnabled);
3188
- const enableWatermark = featureFlagService.isFeatureGateEnabled(FeatureGates.IsWatermarkEnabled);
3189
- const userQueryAwaysEnabled = featureFlagService.isFeatureGateEnabled(FeatureGates.IsUserQueryAlwaysEnabled);
3190
- const isGraphQLUIConfigsEnabled = featureFlagService.isFeatureGateEnabled(FeatureGates.IsGraphQLUIConfigsEnabled);
3191
- const isGraphQLComponentConfigsEnabled = featureFlagService.isFeatureGateEnabled(FeatureGates.IsGraphQLComponentConfigsEnabled);
3192
- let orgUIConfig = { ...localOrgUIConfig };
3193
- if (isGraphQLUIConfigsEnabled && graphqlMerchantOverrideCss) orgUIConfig = {
3194
- ...orgUIConfig,
3195
- merchantOverrideCss: graphqlMerchantOverrideCss
3196
- };
3197
- if (isGraphQLComponentConfigsEnabled && graphqlOrgUIConfig) orgUIConfig = {
3198
- ...orgUIConfig,
3199
- ...graphqlOrgUIConfig
3200
- };
3201
- logger_default.logInfo("[spiffy-ai] Feature gate enableWatermark check", {
3202
- enableWatermark,
3203
- floatingChatConfig: orgUIConfig.floatingChatConfig
3204
- });
3205
- const updatedOrgUIConfig = {
3206
- ...orgUIConfig,
3207
- conversationalSearch: orgUIConfig.conversationalSearch ? {
3208
- ...orgUIConfig.conversationalSearch,
3209
- enabled: isNewFeatureEnabled
3210
- } : void 0,
3211
- customerServiceIntegration: {
3212
- ...orgUIConfig.customerServiceIntegration,
3213
- integrationMode: getCustomerServiceIntegrationMode({
3214
- isNewFeatureEnabled,
3215
- integrationMode: orgUIConfig.customerServiceIntegration?.integrationMode ?? CustomerServiceIntegrationMode.none
3216
- })
3217
- },
3218
- floatingChatConfig: {
3219
- ...orgUIConfig.floatingChatConfig,
3220
- enableWatermark: orgUIConfig.floatingChatConfig?.enableWatermark && enableWatermark,
3221
- userQueryInputEnabled: orgUIConfig.floatingChatConfig?.userQueryInputEnabled || userQueryAwaysEnabled
3222
- }
3223
- };
3224
- atomStore.set(orgUIConfigAtom, updatedOrgUIConfig);
3225
- };
3226
- const orgCustomerServiceConfig = atom((get) => get(orgUIConfigAtom).customerServiceIntegration);
3227
- const orgCustomerServiceService = atom((get) => {
3228
- const { provider } = get(orgCustomerServiceConfig);
3229
- return findCustomerServiceImpl(provider);
3230
- });
3231
-
3232
- //#endregion
3233
- //#region src/atoms/org/org.ts
3234
- const internalApiKeyAtom = atom(void 0);
3235
- const internalEndpointURLAtom = atom(void 0);
3236
- const internalSourceAtom = atom(EnvironmentService.getContextSource());
3237
- const getApiKeyEnvVar = (shortName) => `VITE_${shortName.replace(/-/g, "_").toUpperCase()}_API_KEY`;
3238
- const apiKeyAtom = atom((get) => {
3239
- const apiKey = get(internalApiKeyAtom);
3240
- if (apiKey) return apiKey;
3241
- const { orgLevelApiKey, orgShortName } = useEnviveConfig();
3242
- if (orgLevelApiKey) return orgLevelApiKey;
3243
- if (window._spiffy?.publicKey && typeof window._spiffy.publicKey === "string") return window._spiffy.publicKey;
3244
- if (!orgShortName) throw new Error("[spiffy-ai] orgShortName is required but is not set");
3245
- throw new Error(`[spiffy-ai]: apiKey is missing`);
3246
- }, (_, set, newVal) => {
3247
- set(internalApiKeyAtom, newVal);
3248
- });
3249
- const endpointURLAtom = atom((get) => get(internalEndpointURLAtom) ?? EnvironmentService.getApiEndpoint(), (_, set, newVal) => {
3250
- set(internalEndpointURLAtom, newVal);
3251
- });
3252
- const sourceAtom = atom((get) => get(internalSourceAtom), (_, set, newVal) => {
3253
- set(internalSourceAtom, newVal);
3254
- });
3255
- const orgConfigStorageUtil = createJSONStorage(() => sessionStorage);
3256
- const storedOrgConfigAtom = atomWithStorage("spiffy-org-config", void 0, orgConfigStorageUtil, { getOnInit: true });
3257
- const internalFeatureFlagServiceAtom = atom(void 0);
3258
- const internalOrgConfigAtom = atom(void 0);
3259
- const internalOrgDomainAtom = atom(void 0);
3260
- const internalOrgIdAtom = atom(void 0);
3261
- const internalOrgShortNameAtom = atom(void 0);
3262
- const featureFlagServiceAtom = atom((get) => {
3263
- const featureFlagService = get(internalFeatureFlagServiceAtom);
3264
- if (featureFlagService) return featureFlagService;
3265
- const orgConfig = get(internalOrgConfigAtom);
3266
- if (orgConfig) return new FeatureFlagService(orgConfig.gates);
3267
- throw new Error("FeatureFlagService is referenced before it is set");
3268
- }, (_, set, value) => {
3269
- set(internalFeatureFlagServiceAtom, value);
3270
- });
3271
- const orgConfigAtom = atom((get) => {
3272
- const orgConfig = get(internalOrgConfigAtom);
3273
- if (orgConfig) return orgConfig;
3274
- throw new Error("OrgConfig is referenced before it is set");
3275
- }, (_, set, value) => {
3276
- set(internalOrgConfigAtom, value);
3277
- });
3278
- const orgShortNameAtom = atom((get) => {
3279
- const orgShortName = get(internalOrgShortNameAtom);
3280
- if (orgShortName) return orgShortName;
3281
- throw new Error("Org short name is referenced before it is set");
3282
- }, (_, set, value) => {
3283
- set(internalOrgShortNameAtom, value);
3284
- });
3285
- const orgDomainAtom = atom((get) => {
3286
- const orgDomain = get(internalOrgDomainAtom);
3287
- if (orgDomain) return orgDomain;
3288
- throw new Error("Org domain is referenced before it is set");
3289
- }, (_, set, value) => {
3290
- set(internalOrgDomainAtom, value);
3291
- });
3292
- const orgIdAtom = atom((get) => {
3293
- const orgId = get(internalOrgIdAtom);
3294
- if (orgId) return orgId;
3295
- throw new Error("Org id is referenced before it is set");
3296
- }, (_, set, value) => {
3297
- set(internalOrgIdAtom, value);
3298
- });
3299
- const resetStoredOrgConfigAtom = () => {
3300
- getAtomStore().set(storedOrgConfigAtom, {});
3301
- };
3302
- const getGraphQLConfig = async (atomStore) => {
3303
- const { colorsConfig, frontendConfig } = await GraphQLClient.getColorsAndFrontendConfig() ?? {};
3304
- const rawFrontendConfig = atomStore.get(frontendConfigAtom);
3305
- atomStore.set(colorsConfigAtom, colorsConfig);
3306
- atomStore.set(frontendConfigAtom, {
3307
- ...rawFrontendConfig,
3308
- pageVariants: frontendConfig?.pageVariants,
3309
- mountingConfigs: frontendConfig?.mountingConfigs,
3310
- widgetConfigs: frontendConfig?.widgetConfigs
3311
- });
3312
- await getOrgUIConfig(frontendConfig?.uiConfigs, frontendConfig?.merchantOverrideCss);
3313
- };
3314
- /**
3315
- * This function is used to return an orgConfig corresponding to a given API key
3316
- *
3317
- * @param apiKeyOverride an optional new api key to override the current key stored in apiKeyAtom
3318
- *
3319
- * @returns The OrgAnalyticsConfig object or throws an error if the config was not successfully retrieved
3320
- */
3321
- const getAsyncOrgConfig = async (apiKeyOverride) => {
3322
- const atomStore = getAtomStore();
3323
- const apiKey = apiKeyOverride ?? atomStore.get(apiKeyAtom);
3324
- atomStore.set(apiKeyAtom, apiKey);
3325
- atomStore.set(endpointURLAtom, EnvironmentService.getApiEndpoint());
3326
- atomStore.set(sourceAtom, EnvironmentService.getContextSource());
3327
- atomStore.set(logPerfMetricAtom, PerfMetricsEvents.OrgConfigLoadStarted);
3328
- const maybeOrgConfigByApiKey = atomStore.get(storedOrgConfigAtom);
3329
- let maybeOrgConfig = maybeOrgConfigByApiKey?.[apiKey];
3330
- if (!maybeOrgConfig) {
3331
- const userId = UserIdentityService.getUserIdOrDefault();
3332
- maybeOrgConfig = await api_default.getOrgConfig(userId);
3333
- }
3334
- if (!maybeOrgConfig) throw new Error("[spiffy-ai] Org config is not defined but is required");
3335
- const latestConfig = maybeOrgConfig.configs?.find((config) => config.isLatest);
3336
- if (!latestConfig) throw new Error("[spiffy-ai] no latest org config is found");
3337
- const orgConfig = {
3338
- ...maybeOrgConfig,
3339
- configs: [{ ...latestConfig }]
3340
- };
3341
- if (!orgConfig.org) throw new Error("[spiffy-ai] orgConfig.org is not defined but is required");
3342
- atomStore.set(logPerfMetricAtom, PerfMetricsEvents.OrgConfigLoadEnded);
3343
- atomStore.set(orgShortNameAtom, orgConfig.org.org.shortName);
3344
- atomStore.set(orgDomainAtom, orgConfig.org.org.domain);
3345
- atomStore.set(orgIdAtom, orgConfig.org.org.id);
3346
- atomStore.set(storedOrgConfigAtom, {
3347
- ...maybeOrgConfigByApiKey,
3348
- [apiKey]: orgConfig
3349
- });
3350
- atomStore.set(orgConfigAtom, orgConfig);
3351
- atomStore.set(orgAnalyticsConfigAtom, { ...latestConfig.config });
3352
- atomStore.set(featureFlagServiceAtom, new FeatureFlagService(orgConfig.gates));
3353
- await getGraphQLConfig(atomStore);
3354
- return orgConfig;
3355
- };
3356
-
3357
- //#endregion
3358
- //#region src/adapters/spiffy/commerce/graphql.ts
3359
- const configVersion = () => getQueryParam("spiffy_config_version") || getQueryParam("envive_config_version") || "deployed";
3360
- const colorsAndFrontendConfigQuery = () => `
3361
- query ($version: String = "${configVersion()}") {
3362
- me {
3363
- getProductsConfigByVersion(version: $version) {
3364
- frontend { values }
3365
- colors { values }
3366
- }
3367
- }
3368
- }
3369
- `;
3370
- var GraphQLClient = class GraphQLClient {
3371
- static {
3372
- this.setInstance = (apiKey, basePath) => {
3373
- GraphQLClient.instance = new GraphQLClient(apiKey, basePath);
3374
- };
3375
- }
3376
- static {
3377
- this.getInstance = () => {
3378
- if (!GraphQLClient.instance) {
3379
- const apiKey = getAtomStore().get(apiKeyAtom);
3380
- GraphQLClient.instance = new GraphQLClient(apiKey, EnvironmentService.getApiEndpoint());
3381
- }
3382
- return GraphQLClient.instance;
3383
- };
3384
- }
3385
- constructor(apiKey, basePath) {
3386
- this.apiKey = apiKey;
3387
- this.basePath = basePath;
3388
- }
3389
- async executeQuery(query, variables) {
3390
- const response = await fetch(`${this.basePath}/v1/graphql`, {
3391
- method: "POST",
3392
- headers: {
3393
- "Content-Type": "application/json",
3394
- Authorization: `Bearer ${this.apiKey}`
3395
- },
3396
- body: JSON.stringify({
3397
- query,
3398
- variables
3399
- })
3400
- });
3401
- if (!response.ok) throw new Error(`GraphQL request failed: ${response.statusText}`);
3402
- const result = await response.json();
3403
- if (result.errors) throw new Error(`GraphQL errors: ${JSON.stringify(result.errors)}`);
3404
- return result.data;
3405
- }
3406
- static {
3407
- this.getOrgId = async () => {
3408
- const query = getMerchantOrgIdQuery;
3409
- if (!query) throw new Error("Org id query is not defined");
3410
- const response = await GraphQLClient.getInstance().executeQuery(query);
3411
- return validateGraphQLOrgId(response.me.org?.id);
3412
- };
3413
- }
3414
- static {
3415
- this.getColorsAndFrontendConfig = async () => {
3416
- try {
3417
- const query = colorsAndFrontendConfigQuery();
3418
- if (!query) throw new Error("Colors and frontend config query is not defined");
3419
- const response = await GraphQLClient.getInstance().executeQuery(query);
3420
- return {
3421
- colorsConfig: validateGraphQLColorsConfig(response.me.getProductsConfigByVersion?.colors?.values),
3422
- frontendConfig: validateGraphQLFrontendConfig(response.me.getProductsConfigByVersion?.frontend?.values)
3423
- };
3424
- } catch (err) {
3425
- logger_default.logError("Error fetching graphql colors and frontend config", err);
3426
- return {
3427
- colorsConfig: void 0,
3428
- frontendConfig: void 0
3429
- };
3430
- }
3431
- };
3432
- }
3433
- static {
3434
- this.getFrontendConfig = async () => {
3435
- try {
3436
- const query = getMerchantFrontendConfigQuery();
3437
- if (!query) throw new Error("Frontend config query is not defined");
3438
- const response = await GraphQLClient.getInstance().executeQuery(query);
3439
- if (!response.me.getProductsConfigByVersion?.frontend) throw new Error("No frontend config found");
3440
- return validateGraphQLFrontendConfig(response.me.getProductsConfigByVersion.frontend.values);
3441
- } catch (err) {
3442
- logger_default.logError("Error fetching graphql frontend config", err);
3443
- return;
3444
- }
3445
- };
3446
- }
3447
- static {
3448
- this.getColors = async () => {
3449
- try {
3450
- const query = getMerchantColorsQuery();
3451
- if (!query) throw new Error("Colors query is not defined");
3452
- const response = await GraphQLClient.getInstance().executeQuery(query);
3453
- if (!response.me.getProductsConfigByVersion?.colors) throw new Error("No colors config found");
3454
- return isGraphQLColorsConfig(response.me.getProductsConfigByVersion.colors.values) ? response.me.getProductsConfigByVersion.colors.values : void 0;
3455
- } catch (err) {
3456
- logger_default.logError("Error fetching graphql colors config", err);
3457
- return;
3458
- }
3459
- };
3460
- }
3461
- };
3462
-
3463
- //#endregion
3464
- //#region src/application/models/graphql/queries/getMerchantFrontendConfigQuery.ts
3465
- const getMerchantFrontendConfigQuery = () => `
3466
- query ($version: "${configVersion()}") {
3467
- me {
3468
- getProductsConfigByVersion(version: $version) {
3469
- frontend {
3470
- values
3471
- }
3472
- }
3473
- }
3474
- }
3475
- `;
3476
-
3477
- //#endregion
3478
- //#region src/application/models/graphql/queries/getMerchantColorsQuery.ts
3479
- const getMerchantColorsQuery = () => `
3480
- query ($version: "${configVersion()}") {
3481
- me {
3482
- getProductsConfigByVersion(version: $version) {
3483
- colors {
3484
- values
3485
- }
3486
- }
3487
- }
3488
- }
3489
- `;
3490
-
3491
- //#endregion
3492
- //#region src/application/models/guards/isBaseEcommerceEvent.ts
3493
- /**
3494
- * Checks if an event is a base Google Analytics ecommerce event.
3495
- *
3496
- * @param data The event to check.
3497
- *
3498
- * @returns True if the event is a base ecommerce event, false otherwise.
3499
- */
3500
- const isBaseEcommerceEvent = (data) => data != null && typeof data === "object" && "ecommerce" in data && data.ecommerce != null && typeof data.ecommerce === "object" && "event" in data && typeof data.event === "string";
3501
-
3502
- //#endregion
3503
- //#region src/application/models/guards/isGA4EcommerceEvent.ts
3504
- /**
3505
- * Checks if an event is a Google Analytics 4 ecommerce event.
3506
- *
3507
- * @param data The event to check.
3508
- *
3509
- * @returns True if the event is a GA4 ecommerce event, false otherwise.
3510
- */
3511
- const isGA4EcommerceEvent = (data) => typeof data === "object" && data != null && "ecommerce" in data && data.ecommerce != null && typeof data.ecommerce === "object" && "items" in data.ecommerce && Array.isArray(data.ecommerce.items);
3512
-
3513
- //#endregion
3514
- //#region src/application/models/guards/isLegacyUAEcommerceEvent.ts
3515
- /**
3516
- * Checks if an event is a legacy Universal Analytics ecommerce event.
3517
- *
3518
- * @param data The event to check.
3519
- *
3520
- * @returns True if the event is a legacy UA ecommerce event, false otherwise.
3521
- */
3522
- const isLegacyUAEcommerceEvent = (data) => data != null && typeof data === "object" && "ecommerce" in data && data.ecommerce != null && typeof data.ecommerce === "object" && "add" in data.ecommerce && typeof data.ecommerce.add === "object";
3523
-
3524
- //#endregion
3525
- //#region src/application/models/guards/isMobilePLPChatPlacementParameter.ts
3526
- const isMobilePLPChatPlacementParameter = (value) => value != null && typeof value === "object" && "row_index" in value && typeof value.row_index === "number";
3527
-
3528
- //#endregion
3529
- //#region src/application/models/guards/isSpanxTakeAQuizCtaParameter.ts
3530
- const isSpanxTakeAQuizCtaParameter = (value) => value != null && typeof value === "object" && "text" in value && typeof value.text === "string";
3531
-
3532
- //#endregion
3533
- //#region src/application/models/guards/isVariantInfo.ts
3534
- const isPDPVariantInfo = (variantInfo) => "variant" in variantInfo && variantInfo.variant === "pdp" && "productId" in variantInfo && typeof variantInfo.productId === "string";
3535
- const isPLPVariantInfo = (variantInfo) => "variant" in variantInfo && variantInfo.variant === "plp" && "plpId" in variantInfo && typeof variantInfo.plpId === "string";
3536
- const isPageVisitVariantInfo = (variantInfo) => "variant" in variantInfo && variantInfo.variant === "page_visit" && "url" in variantInfo && typeof variantInfo.url === "string" && "pageVisitCategory" in variantInfo && Object.values(PageVisitCategory).includes(variantInfo.pageVisitCategory);
3537
- /**
3538
- * Type guard to check if an object is a valid VariantInfo.
3539
- *
3540
- * @param variantInfo - The unknown object to check.
3541
- *
3542
- * @returns True if the data is a valid VariantInfo object, false otherwise.
3543
- */
3544
- const isVariantInfo = (variantInfo) => variantInfo != null && typeof variantInfo === "object" && "variantId" in variantInfo && (isPDPVariantInfo(variantInfo) || isPLPVariantInfo(variantInfo) || isPageVisitVariantInfo(variantInfo));
3545
-
3546
- //#endregion
3547
- //#region src/application/models/validators/validateMobilePLPChatPlacementParameter.ts
3548
- const validateMobilePLPChatPlacementParameter = (value) => {
3549
- if (!isMobilePLPChatPlacementParameter(value)) return;
3550
- return { rowIndex: value.row_index };
3551
- };
3552
-
3553
- //#endregion
3554
- //#region src/enabled-features.ts
3555
- var EnabledFeatures = class {
3556
- static {
3557
- this.values = void 0;
3558
- }
3559
- static async get(orgConfig, featureFlagService) {
3560
- if (this.values !== void 0) return this.values;
3561
- const isSpiffyEnabled = async (orgConfig$1, featureFlagService$1) => {
3562
- if (LocalStorageService.getSpiffyOnFeatureFlag() === "true") {
3563
- logger_default.logDebug(`[spiffy-ai] spiffy enabled by "spiffy_on" override`);
3564
- return true;
3565
- }
3566
- if (LocalStorageService.getSpiffyOnFeatureFlag() === "false") {
3567
- logger_default.logDebug(`[spiffy-ai] envive disabled by "envive_on" override`);
3568
- return false;
3569
- }
3570
- if (window._spiffy?.show != null && !window._spiffy.show) {
3571
- logger_default.logDebug(`[spiffy-ai] spiffy disabled by window._spiffy.show`);
3572
- return false;
3573
- }
3574
- if (!featureFlagService$1.isClientSessionEnabled()) {
3575
- logger_default.logDebug(`[spiffy-ai] spiffy disabled by feature flag`);
3576
- return false;
3577
- }
3578
- if (window._spiffy?.show != null && window._spiffy.show) {
3579
- logger_default.logDebug(`[spiffy-ai] spiffy enabled by window._spiffy.show`);
3580
- return true;
3581
- }
3582
- if ((await getOrgInfo(orgConfig$1.org.org.shortName)).alwaysEnabledMerchants) {
3583
- logger_default.logDebug(`[spiffy-ai] spiffy enabled by org config and feature flag`);
3584
- return true;
3585
- }
3586
- if (featureFlagService$1.isClientSessionEnabled()) {
3587
- logger_default.logDebug(`[spiffy-ai] spiffy is enabled by feature flag`);
3588
- return true;
3589
- }
3590
- logger_default.logDebug(`[spiffy-ai] spiffy is disabled because not all checks have passed`);
3591
- return false;
3592
- };
3593
- const isSalesAgentEnabled = isSpiffyEnabled;
3594
- this.values = {
3595
- envive: await isSpiffyEnabled(orgConfig, featureFlagService),
3596
- salesAgent: await isSalesAgentEnabled(orgConfig, featureFlagService)
3597
- };
3598
- return this.values;
3599
- }
3600
- static reset() {
3601
- this.values = void 0;
3602
- }
3603
- };
3604
-
3605
- //#endregion
3606
- //#region src/adapters/amplitude/amplitudeAdapter.ts
3607
- let SpiffyMetricsEventName = /* @__PURE__ */ function(SpiffyMetricsEventName$1) {
3608
- SpiffyMetricsEventName$1["BundleLoaded"] = "Bundle Loaded";
3609
- SpiffyMetricsEventName$1["ChatLiveAgentBtnClick"] = "Chat Live Agent Btn Click";
3610
- SpiffyMetricsEventName$1["ChatFloatingButtonVisible"] = "Chat Floating Button Visible";
3611
- SpiffyMetricsEventName$1["ChatComponentVisible"] = "Chat Component Visible";
3612
- SpiffyMetricsEventName$1["ChatComponentExpanded"] = "Chat Component Expanded";
3613
- SpiffyMetricsEventName$1["ChatComponentCollapsed"] = "Chat Component Collapsed";
3614
- SpiffyMetricsEventName$1["ChatUserMessageInput"] = "Chat User Message Input";
3615
- SpiffyMetricsEventName$1["ChatSuggestionClicked"] = "Chat Suggestion Clicked";
3616
- SpiffyMetricsEventName$1["ChatAssistantResponse"] = "Chat Assistant Response";
3617
- SpiffyMetricsEventName$1["ProductCardClicked"] = "Product Card Clicked";
3618
- SpiffyMetricsEventName$1["ProductReviewCardClicked"] = "Product Review Card Clicked";
3619
- SpiffyMetricsEventName$1["AddToCartClicked"] = "Add to Cart Clicked";
3620
- SpiffyMetricsEventName$1["PromptCardClicked"] = "Prompt Card Clicked";
3621
- SpiffyMetricsEventName$1["SupportedEvent"] = "Supported Event";
3622
- SpiffyMetricsEventName$1["SearchBackToResponseClicked"] = "Search Back to Response Clicked";
3623
- SpiffyMetricsEventName$1["PerformanceMetrics"] = "Performance Metrics";
3624
- SpiffyMetricsEventName$1["SearchBarClicked"] = "Search Bar Clicked";
3625
- SpiffyMetricsEventName$1["OrderLookupStarted"] = "Order Lookup Started";
3626
- SpiffyMetricsEventName$1["OrderLookupFormSubmitted"] = "Order Lookup Form Submitted";
3627
- SpiffyMetricsEventName$1["SearchComponentVisible"] = "Search Component Visible";
3628
- SpiffyMetricsEventName$1["GlobalSearchPromptClicked"] = "Global Search Prompt Clicked";
3629
- SpiffyMetricsEventName$1["SearchInputStarted"] = "Search Input Started";
3630
- SpiffyMetricsEventName$1["SearchQuerySubmitted"] = "Search Query Submitted";
3631
- SpiffyMetricsEventName$1["SearchResultsViewed"] = "Search Results Viewed";
3632
- SpiffyMetricsEventName$1["SearchTimeToFirstClick"] = "Search Time to First Click";
3633
- SpiffyMetricsEventName$1["SearchZeroResultsRate"] = "Search Zero Results Rate";
3634
- SpiffyMetricsEventName$1["SearchFilterClicked"] = "Search Filter Clicked";
3635
- SpiffyMetricsEventName$1["SearchSortClicked"] = "Search Sort Clicked";
3636
- return SpiffyMetricsEventName$1;
3637
- }({});
3638
- var AmplitudeAdapter = class AmplitudeAdapter {
3639
- constructor(userId, orgConfig, featureFlagService, orgGaConfig) {
3640
- this.userId = userId;
3641
- this.orgConfig = orgConfig;
3642
- this.featureFlagService = featureFlagService;
3643
- this.orgGaConfig = orgGaConfig;
3644
- this.underlyingAmplitudeClient = void 0;
3645
- this.internalEventTrackingEnrichment = void 0;
3646
- this.eventPropsToPrefixedEventProps = (eventName, eventProps) => {
3647
- const prefix = eventName.toLowerCase().replace(/\s+/g, "_");
3648
- return Object.entries(eventProps).reduce((acc, [key, value]) => {
3649
- acc[`${prefix}.${key}`] = value;
3650
- return acc;
3651
- }, {});
3652
- };
3653
- this.supplementalDefaultProps = {};
3654
- }
3655
- init() {
3656
- this.underlyingAmplitudeClient = this.createUnderlyingClient();
3657
- }
3658
- getUnderlyingAmplitudeClient() {
3659
- return this.underlyingAmplitudeClient;
3660
- }
3661
- getSupplementalDefaultProps() {
3662
- return this.supplementalDefaultProps;
3663
- }
3664
- setSupplementalDefaultProps(supplementalDefaultProps) {
3665
- this.supplementalDefaultProps = supplementalDefaultProps;
3666
- }
3667
- getEventTrackingEnrichment() {
3668
- if (this.internalEventTrackingEnrichment !== void 0) return this.internalEventTrackingEnrichment;
3669
- this.internalEventTrackingEnrichment = {
3670
- name: "page-view-tracking-enrichment",
3671
- type: "enrichment",
3672
- setup: async () => void 0,
3673
- execute: async (event) => {
3674
- let enrichedEvent;
3675
- if (["[Amplitude] Page Viewed", `[Spiffy] ${SpiffyMetricsEventName.BundleLoaded}`].includes(event.event_type)) {
3676
- const windowProps = window._spiffy ? { ...window._spiffy } : {};
3677
- if (windowProps.publicKey) delete windowProps.publicKey;
3678
- const globalProperties = Object.entries(windowProps).reduce((acc, [key, value]) => ({
3679
- ...acc,
3680
- [`globalProperties.${key}`]: `${value}`
3681
- }), {});
3682
- const enabledFeatures = await EnabledFeatures.get(this.orgConfig, this.featureFlagService);
3683
- const enabledFeaturesProperties = Object.entries(enabledFeatures).reduce((acc, [key, value]) => ({
3684
- ...acc,
3685
- [`enabledFeatures.${key}`]: `${value}`
3686
- }), {});
3687
- const timingProperties = { "timing.enriched_at_ms": window.performance?.now() };
3688
- enrichedEvent = {
3689
- ...event,
3690
- event_properties: {
3691
- ...event.event_properties,
3692
- ...this.getDefaultTrackingProps(),
3693
- ...globalProperties,
3694
- ...enabledFeaturesProperties,
3695
- ...timingProperties
3696
- }
3697
- };
3698
- } else enrichedEvent = event;
3699
- EventsDispatcher.dispatch(SpiffyEvent.AMPLITUDE_EVENT, enrichedEvent);
3700
- return enrichedEvent;
3701
- }
3702
- };
3703
- return this.internalEventTrackingEnrichment;
3704
- }
3705
- amplitudeSessionReplayInit() {
3706
- const isEnabled = this.orgConfig.org.org.shortName === OrgShortName.UniqueVintage && this.featureFlagService.isClientSessionEnabled() && this.featureFlagService.isFeatureGateEnabled(FeatureGates.IsNewFeatureEnabled);
3707
- const sampleRate = 1;
3708
- try {
3709
- logger_default.logDebug(`[spiffy-ai] amplitude session-replay initializing isEnabled=${isEnabled} sampleRate=${sampleRate}`);
3710
- if (!isEnabled) return isEnabled;
3711
- return isEnabled;
3712
- } catch (e) {
3713
- logger_default.logError("[spiffy-ai] Error initializing amplitude session-replay", e);
3714
- return false;
3715
- }
3716
- }
3717
- createUnderlyingClient() {
3718
- const { amplitudeApiKey, dataResidency } = useEnviveConfig();
3719
- const currentAmplitudeInstance = createInstance();
3720
- const isSessionsEnabled = this.amplitudeSessionReplayInit();
3721
- currentAmplitudeInstance.add(this.getEventTrackingEnrichment());
3722
- currentAmplitudeInstance.init(amplitudeApiKey, this.userId, {
3723
- serverZone: dataResidency,
3724
- trackingOptions: { ipAddress: true },
3725
- autocapture: {
3726
- attribution: true,
3727
- pageViews: { trackHistoryChanges: "pathOnly" },
3728
- sessions: isSessionsEnabled,
3729
- formInteractions: false,
3730
- fileDownloads: false
3731
- }
3732
- });
3733
- return currentAmplitudeInstance;
3734
- }
3735
- getDefaultTrackingProps() {
3736
- const { env } = useEnviveConfig();
3737
- const gatesProps = this.orgConfig.gates ? this.orgConfig.gates.reduce((acc, curr) => {
3738
- if (curr.name && curr.value != null) return {
3739
- ...acc,
3740
- [`feature_gate.${curr.name}`]: curr.value
3741
- };
3742
- return acc;
3743
- }, {}) : {};
3744
- const experimentProps = this.orgConfig.experiments ? this.orgConfig.experiments.reduce((acc, curr) => {
3745
- if (curr.name && curr.value != null) return {
3746
- ...acc,
3747
- [`product_experiment.${curr.name}`]: curr.value
3748
- };
3749
- return acc;
3750
- }, {}) : {};
3751
- return {
3752
- ...gatesProps,
3753
- ...experimentProps,
3754
- ...this.supplementalDefaultProps,
3755
- org_id: this.orgConfig.org?.org.id,
3756
- app_id: "commerce-chat-react-component",
3757
- chat_id: LocalStorageService.getItem(LocalStorageKeys.ChatId),
3758
- env: env || "unknown",
3759
- app_source: EnvironmentService.getContextSource(),
3760
- "org.short_name": this.orgConfig.org?.org.shortName,
3761
- "user.id": this.userId,
3762
- "cdp.user_id": null,
3763
- "cdp.provider": null,
3764
- "event.source": "web-browser",
3765
- "event.type": "user-activity",
3766
- "event.id": null,
3767
- "event.channel": "web",
3768
- "event.timestamp": null
3769
- };
3770
- }
3771
- static {
3772
- this.trackEvent = async ({ eventName, eventProps, eventGroups, alsoSendToGoogleAnalytics = false }) => {
3773
- try {
3774
- const decoratedEventName = `[Spiffy] ${eventName}`;
3775
- const amplitudeInstance = AmplitudeAdapter.getSingletonInstanceOf();
3776
- const amplitudeClient = amplitudeInstance.getUnderlyingAmplitudeClient();
3777
- if (!amplitudeClient) {
3778
- logger_default.logWarn("amplitude instance undefined", void 0, { event_name: decoratedEventName });
3779
- return;
3780
- }
3781
- const eventData = JSON.stringify({
3782
- eventName,
3783
- eventProps,
3784
- created_at: (/* @__PURE__ */ new Date()).toISOString()
3785
- });
3786
- const data = new TextEncoder().encode(eventData);
3787
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
3788
- const currentInsertId = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
3789
- logger_default.logDebug(`amplitude tracking ${decoratedEventName}`, null, {
3790
- event_name: decoratedEventName,
3791
- props: eventProps
3792
- });
3793
- amplitudeClient.track(decoratedEventName, {
3794
- ...amplitudeInstance.getDefaultTrackingProps(),
3795
- ...eventProps,
3796
- ...eventProps ? AmplitudeAdapter.getSingletonInstanceOf().eventPropsToPrefixedEventProps(eventName, eventProps) : {}
3797
- }, {
3798
- ...eventGroups,
3799
- insert_id: currentInsertId
3800
- });
3801
- if (alsoSendToGoogleAnalytics && amplitudeInstance.orgGaConfig) {
3802
- const dataLayer = WindowDataLayerService.getSingletonInstanceOf(amplitudeInstance.orgGaConfig);
3803
- logger_default.logDebug("[spiffy-ai] GA tracking", decoratedEventName);
3804
- dataLayer.sendToGoogleAnalyticsCircularEventsSafe(decoratedEventName, eventProps);
3805
- }
3806
- } catch (err) {
3807
- logger_default.logError("[spiffy-ai] Error tracking event", err, {
3808
- eventName,
3809
- eventProps
3810
- });
3811
- }
3812
- };
3813
- }
3814
- static amplitudeSafeString(input) {
3815
- if (!input) return null;
3816
- if (input.length > 1024) return input.slice(0, 1024);
3817
- return input;
3818
- }
3819
- static getSingletonInstanceOf() {
3820
- if (EnvironmentService.getContextSource() === ContextSourceEnum.Test) return new StubAmplitudeAdapter();
3821
- const identifyingPrefix = EnvironmentService.getIdentifyingPrefix();
3822
- if (!window[identifyingPrefix]) window[identifyingPrefix] = {};
3823
- if (!window[identifyingPrefix]._amplitudeAdapter) {
3824
- const atomStore = getAtomStore();
3825
- const userId = atomStore.get(userIdAtom);
3826
- const orgConfig = atomStore.get(orgConfigAtom);
3827
- const orgGaConfig = atomStore.get(orgAnalyticsGoogleAnalyticsConfigAtom);
3828
- const featureFlagService = atomStore.get(featureFlagServiceAtom);
3829
- window[identifyingPrefix]._amplitudeAdapter = new AmplitudeAdapter(userId, orgConfig, featureFlagService, orgGaConfig);
3830
- window[identifyingPrefix]._amplitudeAdapter?.init();
3831
- }
3832
- return window[identifyingPrefix]._amplitudeAdapter;
3833
- }
3834
- };
3835
-
3836
- //#endregion
3837
- //#region src/adapters/amplitude/stubAmplitudeAdapter.ts
3838
- var StubAmplitudeAdapter = class extends AmplitudeAdapter {
3839
- constructor() {
3840
- super("test", {}, {});
3841
- this.init = () => {};
3842
- this.getUnderlyingAmplitudeClient = () => void 0;
3843
- this.getSupplementalDefaultProps = () => ({});
3844
- this.setSupplementalDefaultProps = () => {};
3845
- this.getEventTrackingEnrichment = () => ({
3846
- name: "stub-enrichment",
3847
- type: "enrichment",
3848
- setup: async () => void 0,
3849
- execute: async (event) => event
3850
- });
3851
- this.amplitudeSessionReplayInit = () => false;
3852
- this.createUnderlyingClient = () => ({});
3853
- this.getDefaultTrackingProps = () => ({});
3854
- this.trackEvent = () => Promise.resolve();
3855
- }
3856
- };
3857
-
3858
- //#endregion
3859
- //#region src/atoms/chat/chatState.ts
3860
- const userHasRepliedAtom = atom(false);
3861
- const replyEventCategoryAtom = atom(UserEventCategory.AppLoaded);
3862
- const userQueryAtom = atom();
3863
- const suggestionAtom = atom(void 0);
3864
- const askQuestionBtnClickedAtom = atom(false);
3865
- const messagesAtom = atom([]);
3866
- const userEventsAtom = atom([]);
3867
- const suggestionsAtom = atom([]);
3868
- const suggestionsLoadingAtom = atom(false);
3869
- const responseStreamingAtom = atom(false);
3870
- const chatIsOpenAtom = atom(false);
3871
- const requestFailureAtom = atom(false);
3872
- const formSubmitAtom = atom();
3873
- const chatOnToggleAtom = atom(null, (get, set, triggerLocation) => {
3874
- const isOpen = get(chatIsOpenAtom);
3875
- set(chatIsOpenAtom, !isOpen);
3876
- if (!isOpen) {
3877
- window.dispatchEvent(new CustomEvent(SpiffyEventName.WidgetOpen));
3878
- AmplitudeAdapter.trackEvent({
3879
- eventName: SpiffyMetricsEventName.ChatComponentExpanded,
3880
- eventProps: { message_metadata: { trigger_location: triggerLocation } }
3881
- });
3882
- } else {
3883
- window.dispatchEvent(new CustomEvent(SpiffyEventName.WidgetClose));
3884
- AmplitudeAdapter.trackEvent({ eventName: SpiffyMetricsEventName.ChatComponentCollapsed });
3885
- }
3886
- });
3887
-
3888
- //#endregion
3889
- //#region src/atoms/chat/messageQueue.ts
3890
- const internalUserEventQueueAtom = atom([]);
3891
- const userEventQueueAtom = atom((get) => {
3892
- const queue = get(internalUserEventQueueAtom);
3893
- return queue === void 0 ? [] : queue.filter((v) => v !== void 0);
3894
- });
3895
- /**
3896
- * This atom is used to queue a new message for processing on `next_responses`
3897
- * It receives a single `userEvent` that is added to the processing queue.
3898
- * If the event has the same eventId as an existing message in the queue the NEW
3899
- * event is ignored
3900
- */
3901
- const queueUserEventAtom = atom(null, (get, set, userEvent) => {
3902
- if (userEvent === void 0) return;
3903
- set(internalUserEventQueueAtom, [...get(internalUserEventQueueAtom), userEvent]);
3904
- });
3905
- /**
3906
- * This atom exposes a function to reset the entire queue. All messages in the queue will be purged
3907
- */
3908
- const clearUserEventAtom = atom(null, (_, set) => {
3909
- set(internalUserEventQueueAtom, []);
3910
- });
3911
- /**
3912
- * This atom is used to mark events as processed and remove them from the queue
3913
- * It accepts a list of eventId values and will remove all events with those eventIds from the queue.
3914
- */
3915
- const processUserEventAtom = atom(null, (get, set, eventIds) => {
3916
- const remaining = get(internalUserEventQueueAtom)?.filter((event) => !eventIds.includes(event.eventId));
3917
- set(internalUserEventQueueAtom, remaining);
3918
- });
3919
- const userQueueEventCountAtom = atom((get) => get(userEventQueueAtom).length);
3920
- const createResponsePayload = ({ userEvents, generationParams }) => {
3921
- const atomStore = getAtomStore();
3922
- const context = atomStore.get(appDetailsAtom);
3923
- const featureFlags = atomStore.get(featureFlagServiceAtom).getFeatureFlags();
3924
- return {
3925
- id: v4(),
3926
- context,
3927
- userEvents,
3928
- featureFlags,
3929
- generationParams
3930
- };
3931
- };
3932
-
3933
- //#endregion
3934
- //#region src/atoms/chat/replies.ts
3935
- const handleReplyAtom = atom(null, (get, set, { message, userTyped }) => {
3936
- if (message.type !== MessageType.QueryTyped) return;
3937
- const queryTyped = message.metadata.content;
3938
- set(replyEventCategoryAtom, UserEventCategory$1.QueryTyped);
3939
- set(userQueryAtom, queryTyped);
3940
- set(messagesAtom, [...get(messagesAtom), [message]]);
3941
- set(userHasRepliedAtom, true);
3942
- set(queueUserEventAtom, {
3943
- eventId: message.id,
3944
- createdAt: message.createdAt,
3945
- category: UserEventCategory$1.QueryTyped,
3946
- attributes: { query: queryTyped }
3947
- });
3948
- AmplitudeAdapter.trackEvent({
3949
- eventName: SpiffyMetricsEventName.ChatUserMessageInput,
3950
- eventProps: {
3951
- message_id: message.id,
3952
- message_role: message.role,
3953
- message_type: message.type,
3954
- message_metadata: {
3955
- content: AmplitudeAdapter.amplitudeSafeString(message?.metadata?.content),
3956
- created_at: message.createdAt,
3957
- user_typed: userTyped
3958
- }
3959
- },
3960
- alsoSendToGoogleAnalytics: true
3961
- });
3962
- });
3963
-
3964
- //#endregion
3965
- //#region src/atoms/chat/performanceMetrics.ts
3966
- const APP_INITIAL_START_TIME_KEY = "spiffy-app-initial-start-time";
3967
- const PAGE_LOAD_OFFSET_TIME_KEY = "spiffy-page-load-offset-time";
3968
- /**
3969
- * The different performance metrics that can be logged. All times are relative to the
3970
- * initial start time of the app and are stored in milliseconds.
3971
- */
3972
- let PerfMetricsEvents = /* @__PURE__ */ function(PerfMetricsEvents$1) {
3973
- PerfMetricsEvents$1["PageLoadOffset"] = "page_load_offset_ms";
3974
- PerfMetricsEvents$1["MainBundleLoaded"] = "main_bundle_loaded_ms";
3975
- PerfMetricsEvents$1["OrgConfigLoadStarted"] = "org_config_load_started_ms";
3976
- PerfMetricsEvents$1["OrgConfigLoadEnded"] = "org_config_load_ended_ms";
3977
- PerfMetricsEvents$1["FirstResponseStarted"] = "first_response_started_ms";
3978
- PerfMetricsEvents$1["FirstResponseCompleted"] = "first_response_completed_ms";
3979
- PerfMetricsEvents$1["FirstSuggestionsStarted"] = "first_suggestions_started_ms";
3980
- PerfMetricsEvents$1["FirstSuggestionsCompleted"] = "first_suggestions_completed_ms";
3981
- PerfMetricsEvents$1["EmbeddedWidgetRendered"] = "embedded_widget_rendered_ms";
3982
- PerfMetricsEvents$1["FloatingButtonRendered"] = "floating_button_rendered_ms";
3983
- PerfMetricsEvents$1["TopSuggestionsBarRendered"] = "top_suggestions_bar_rendered_ms";
3984
- PerfMetricsEvents$1["BottomSuggestionsBarRendered"] = "bottom_suggestions_bar_rendered_ms";
3985
- PerfMetricsEvents$1["SearchPromptRendered"] = "search_prompt_rendered_ms";
3986
- return PerfMetricsEvents$1;
3987
- }({});
3988
- const internalPerfMetricsAtom = atom(/* @__PURE__ */ new Map());
3989
- const appInitialStartTimeMsAtom = atomWithStorage(APP_INITIAL_START_TIME_KEY, sessionStorage.getItem(APP_INITIAL_START_TIME_KEY) ?? void 0, sessionStorageUtil, { getOnInit: true });
3990
- const pageLoadOffsetTimeAtom = atomWithStorage(PAGE_LOAD_OFFSET_TIME_KEY, sessionStorage.getItem(PAGE_LOAD_OFFSET_TIME_KEY) ?? void 0, sessionStorageUtil, { getOnInit: true });
3991
- /**
3992
- * Resets the performance metrics atom to an empty map. This should be called after the performance
3993
- * metrics have been reported to amplitude. On SPA, it ensures that we can still capture metrics as
3994
- * the user navigates around the app (although there is more work to be done to fully enable this).
3995
- * On non-SPA, it ensures that previously captured metrics are not reported again.
3996
- */
3997
- const resetPerformanceMetricsAtom = () => {
3998
- getAtomStore().set(internalPerfMetricsAtom, /* @__PURE__ */ new Map());
3999
- };
4000
- const performanceMetricsAtom = atom((get) => get(internalPerfMetricsAtom));
4001
- const hasReportedPerformanceMetricsAtom = atom(false);
4002
- /**
4003
- * Logs a performance metric by capturing the delta between the initial app start time
4004
- * and the current time. If the metric has already been logged, it will not be logged again.
4005
- *
4006
- * @param value The performance metric name to log.
4007
- */
4008
- const logPerfMetricAtom = atom(null, (get, set, value) => {
4009
- const initialTimeStorageValue = get(appInitialStartTimeMsAtom);
4010
- const initialTimeMs = initialTimeStorageValue ? parseInt(initialTimeStorageValue, 10) : void 0;
4011
- if (initialTimeMs == null) {
4012
- logger_default.logWarn(`[spiffy-ai] No initial app start time found. Skipping...`, void 0);
4013
- return;
4014
- }
4015
- const currentPerfMetrics = get(internalPerfMetricsAtom);
4016
- if (currentPerfMetrics.has(value)) return;
4017
- const deltaMs = Date.now() - initialTimeMs;
4018
- currentPerfMetrics.set(value, deltaMs);
4019
- set(internalPerfMetricsAtom, currentPerfMetrics);
4020
- });
4021
-
4022
- //#endregion
4023
- //#region src/atoms/chat/form.ts
4024
- const handleFormSubmittedAtom = atom(null, (_, set, form) => {
4025
- set(replyEventCategoryAtom, UserEventCategory$1.FormSubmitted);
4026
- set(formSubmitAtom, form);
4027
- const formUserEvent = {
4028
- eventId: v4(),
4029
- category: UserEventCategory$1.FormSubmitted,
4030
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4031
- attributes: form
4032
- };
4033
- set(queueUserEventAtom, formUserEvent);
4034
- });
4035
-
4036
- //#endregion
4037
- //#region src/atoms/chat/suggestions.ts
4038
- const handleSuggestionAtom = atom(null, (get, set, suggestion) => {
4039
- const newMessage = {
4040
- id: suggestion.id,
4041
- role: MessageRole.User,
4042
- type: MessageType.SuggestionClicked,
4043
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4044
- metadata: {
4045
- suggestionId: suggestion.id,
4046
- suggestionContent: suggestion.content
4047
- }
4048
- };
4049
- set(replyEventCategoryAtom, UserEventCategory$1.SuggestionClicked);
4050
- set(suggestionAtom, suggestion);
4051
- set(messagesAtom, [...get(messagesAtom), [newMessage]]);
4052
- set(userHasRepliedAtom, true);
4053
- set(queueUserEventAtom, {
4054
- eventId: suggestion.id,
4055
- category: UserEventCategory$1.SuggestionClicked,
4056
- createdAt: newMessage.createdAt,
4057
- attributes: { suggestionId: suggestion.id }
4058
- });
4059
- });
4060
-
4061
- //#endregion
4062
- //#region src/atoms/chat/lastMessage.ts
4063
- const lastAssistantMessageAtom = atom((get) => {
4064
- const messages = get(messagesAtom);
4065
- const userHasReplied = get(userHasRepliedAtom);
4066
- if (messages.length > 0 && !userHasReplied) return messages[messages.length - 1];
4067
- return null;
4068
- });
4069
-
4070
- //#endregion
4071
- //#region src/atoms/chat/renderedWidgetRefs.ts
4072
- const internalWidgetArrayAtom = atom([]);
4073
- const widgetArrayAtom = atom((get) => get(internalWidgetArrayAtom));
4074
- /**
4075
- * This function call is used to create a list of the Spiffy widgets
4076
- * that are rendering on the page.
4077
- *
4078
- * It is used by the FloatingButton widget to slide out of view when it
4079
- * overlaps with another Spiffy widget.
4080
- *
4081
- * The spiffy widgets should be added to the this array for the floating button
4082
- * to know about them.
4083
- *
4084
- * Today the "SuggestionBar" widget is not added, but the other widgets are.
4085
- *
4086
- */
4087
- const addWidget = (ref, idx) => {
4088
- const atomStore = getAtomStore();
4089
- const val = atomStore.get(internalWidgetArrayAtom);
4090
- const insertIdx = idx ?? val.length;
4091
- val[insertIdx] = ref;
4092
- atomStore.set(internalWidgetArrayAtom, val);
4093
- };
4094
-
4095
- //#endregion
4096
- //#region src/atoms/chat/index.ts
4097
- const chatAtom = atom((get) => ({
4098
- userHasReplied: get(userHasRepliedAtom),
4099
- replyEventCategory: get(replyEventCategoryAtom),
4100
- userQuery: get(userQueryAtom),
4101
- suggestion: get(suggestionAtom),
4102
- askQuestionBtnClicked: get(askQuestionBtnClickedAtom),
4103
- messages: get(messagesAtom),
4104
- userEvents: get(userEventsAtom),
4105
- suggestions: get(suggestionsAtom),
4106
- suggestionsLoading: get(suggestionsLoadingAtom),
4107
- responseStreaming: get(responseStreamingAtom),
4108
- isOpen: get(chatIsOpenAtom),
4109
- onToggle: get(chatOnToggleAtom)
4110
- }));
4111
-
4112
- //#endregion
4113
- export { APP_INITIAL_START_TIME_KEY, AmplitudeAdapter, ChatElementDisplayLocation, DOMInsertionService, DOMInsertionType, DOMInsertionTypeToInsertPosition, DOMObserver, DomMutationObserverContinuation, DomObservationStrategy, ElementObserver, EnvironmentService, FeatureFlagService, FeatureGates, GoogleAnalyticsEvents, GridInsertionService, GridInsertionType, LocalStorageKeys, LocalStorageService, MessageRole, MessageType, MutationHelper, NodeSelector, PAGE_LOAD_OFFSET_TIME_KEY, PerfMetricsEvents, ProductExperiment, SelectorFactory, SessionRestartRequired, SessionStorageService, SpiffyEventName, SpiffyMetricsEventName, SpiffyWidgets, StringUtils, StubAmplitudeAdapter, UnsupportedProductException, UserIdentityService, WindowDataLayerService, addWidget, apiKeyAtom, api_default, appDetailsAtom, appInitialStartTimeMsAtom, appSourceAtom, applyOverrides, askQuestionBtnClickedAtom, buildSearchHash, buildSearchStartHash, chatAtom, chatIdAtom, chatIsOpenAtom, chatOnToggleAtom, clearUserEventAtom, colorsConfigAtom, coreContextToApiContext, coreSupportedEventRequestToApiRequest, coreUserEventToApiUserEvent, createResponsePayload, createUrlWithQueryParams, divideArray, endpointURLAtom, envAtom, featureFlagServiceAtom, formSubmitAtom, frontendConfigAtom, getApiKeyEnvVar, getAsyncOrgConfig, getMerchantColorsQuery, getMerchantFrontendConfigQuery, getMerchantOrgIdQuery, getOrgUIConfig, getQueryParam, getRecentProductImageUrls, handleFormSubmittedAtom, handleReplyAtom, handleSuggestionAtom, hasParsedVariantInfoAtom, hasReportedPerformanceMetricsAtom, initAmplitude, initDataLayerWrapper, isApiFormResponseAttributes, isApiFormSubmittedResponseAttributes, isApiOrderResponseAttributes, isApiOrgConfigResults, isApiOrganizationConfig, isApiPLPEventAttributes, isApiPLPIdAttribute, isApiPageResponseAttributes, isApiProductSearchFilterResponseAttributes, isBaseEcommerceEvent, isGA4EcommerceEvent, isGraphQLColorsConfig, isLegacyUAEcommerceEvent, isMobilePLPChatPlacementParameter, isSpanxTakeAQuizCtaParameter, isVariantInfo, lastAssistantMessageAtom, logPerfMetricAtom, messageFromFormSubmittedEvent, messageFromQueryEvent, messageFromResponse, messageFromSuggestionEvent, messageRequestToCommerceMessageRequest, messagesAtom, orgAnalyticsAmplitudeConfigAtom, orgAnalyticsConfigAtom, orgAnalyticsCustomerServiceConfigAtom, orgAnalyticsGoogleAnalyticsConfigAtom, orgConfigAtom, orgCustomerServiceConfig, orgCustomerServiceService, orgDomainAtom, orgIdAtom, orgShortNameAtom, orgUIConfigAtom, pageLoadOffsetTimeAtom, parseHref, parseSearchHash, performanceMetricsAtom, prepareMerchantPage, processUserEventAtom, queueUserEventAtom, replyEventCategoryAtom, requestFailureAtom, resetPerformanceMetricsAtom, resetStoredOrgConfigAtom, responseStreamingAtom, sourceAtom, storedOrgConfigAtom, stringToFulfillmentDisplayStatusEnumValue, suggestionAtom, suggestionsAtom, suggestionsLoadingAtom, supportedEventAtom, transformCamelToSnake, transformSnakeToCamel, urlResolverAtom, userEventQueueAtom, userEventsAtom, userHasRepliedAtom, userIdAtom, userQueryAtom, userQueueEventCountAtom, validateAndTransformMountingConfig, validateAndTransformPageVariants, validateAndTransformWidgetConfig, validateEmail, validateGraphQLColorsConfig, validateGraphQLFrontendConfig, validateGraphQLOrgId, validateMobilePLPChatPlacementParameter, validateOrgConfigResults, validateOrganizationConfig, validateResponse, validateSuggestion, validateUserEvent, variantInfoAtom, widgetArrayAtom };