@envive-ai/react-hooks 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/LICENSE +2 -0
  2. package/README.md +2 -0
  3. package/dist/GridInsertionService-CEYo9pGj.js +22 -0
  4. package/dist/GridInsertionService-CS_bnPh0.cjs +28 -0
  5. package/dist/bandolier-Ble8jEa8.js +1221 -0
  6. package/dist/bandolier-Bm2xAt_j.cjs +1221 -0
  7. package/dist/carpe-Da7b-LCW.cjs +599 -0
  8. package/dist/carpe-W13mhRRP.js +597 -0
  9. package/dist/cdnService-CZ-aXcY6.cjs +23 -0
  10. package/dist/cdnService-zQfKk3Eb.js +18 -0
  11. package/dist/chatElementDisplayLocation-CX8fuNao.d.cts +239 -0
  12. package/dist/chatElementDisplayLocation-CwptS9tx.d.ts +239 -0
  13. package/dist/chunk-CUT6urMc.cjs +30 -0
  14. package/dist/contexts/index.cjs +13 -0
  15. package/dist/contexts/index.d.cts +65 -0
  16. package/dist/contexts/index.d.ts +66 -0
  17. package/dist/contexts/index.js +7 -0
  18. package/dist/contexts-BRjfVq_k.js +5064 -0
  19. package/dist/contexts-BYArqZtK.cjs +5164 -0
  20. package/dist/coterie-3y0D9ko4.cjs +229 -0
  21. package/dist/coterie-DOWcJAYv.js +229 -0
  22. package/dist/custservice-types-CFIFwZ-r.js +10 -0
  23. package/dist/custservice-types-CkfxZiHY.cjs +16 -0
  24. package/dist/default-C2fEZKXk.js +175 -0
  25. package/dist/default-CBUq6Q6G.cjs +4 -0
  26. package/dist/default-CGIFZK6m.js +4 -0
  27. package/dist/default-D_KPZdPJ.cjs +198 -0
  28. package/dist/divIds-Bss-btao.js +49 -0
  29. package/dist/divIds-DnZNd7rA.cjs +223 -0
  30. package/dist/dreamlandBaby-DCIsuU9R.cjs +338 -0
  31. package/dist/dreamlandBaby-DvSaZGrz.js +338 -0
  32. package/dist/entrypoints-D_JUvkgy.cjs +18 -0
  33. package/dist/entrypoints-YLQsbBRD.js +6 -0
  34. package/dist/enviveConfigContext-CUGLpPGU.js +34 -0
  35. package/dist/enviveConfigContext-Dfr2VH6u.cjs +48 -0
  36. package/dist/fiveCbd-B1SESMCO.js +605 -0
  37. package/dist/fiveCbd-CkOlVby_.cjs +605 -0
  38. package/dist/forLoveAndLemons-CfYPMnKS.cjs +660 -0
  39. package/dist/forLoveAndLemons-DmwYZIk0.js +658 -0
  40. package/dist/greenpan-Bsl3ir59.cjs +389 -0
  41. package/dist/greenpan-BtOi45lf.js +389 -0
  42. package/dist/grooveLife-6_dtYsRk.js +334 -0
  43. package/dist/grooveLife-Cmm1PSCL.cjs +334 -0
  44. package/dist/homegrownCannabis-C-kw-74X.js +400 -0
  45. package/dist/homegrownCannabis-CO0uY_mp.cjs +400 -0
  46. package/dist/hooks/index.cjs +16 -0
  47. package/dist/hooks/index.d.cts +357 -0
  48. package/dist/hooks/index.d.ts +357 -0
  49. package/dist/hooks/index.js +7 -0
  50. package/dist/jackArcher-CLVmwwpI.js +719 -0
  51. package/dist/jackArcher-DdYTIzAV.cjs +719 -0
  52. package/dist/jordanCraig-Am-Oor-O.js +1778 -0
  53. package/dist/jordanCraig-_u3-w4Hp.cjs +1778 -0
  54. package/dist/kindredBravely-CWovIDSc.cjs +482 -0
  55. package/dist/kindredBravely-eWp-ud_E.js +482 -0
  56. package/dist/kutFromTheKloth-BMV4BuGQ.js +361 -0
  57. package/dist/kutFromTheKloth-Q589bAOC.cjs +361 -0
  58. package/dist/larryAndSerges-BMUlTgI-.js +252 -0
  59. package/dist/larryAndSerges-CEau764j.cjs +252 -0
  60. package/dist/leapsAndRebounds-DGMzPO7T.js +352 -0
  61. package/dist/leapsAndRebounds-DHAtRTJD.cjs +352 -0
  62. package/dist/logger-Dln20ans.cjs +25 -0
  63. package/dist/logger-pdEEY8T2.js +19 -0
  64. package/dist/longevityrx-CZW8Hxzi.cjs +312 -0
  65. package/dist/longevityrx-jH2JLhNH.js +312 -0
  66. package/dist/lookOptic-BGXP5P_V.js +274 -0
  67. package/dist/lookOptic-CA6RwLbG.cjs +274 -0
  68. package/dist/mantraBrand-Cm9_PBCT.js +742 -0
  69. package/dist/mantraBrand-DByNqpnL.cjs +742 -0
  70. package/dist/medterra-B0wxj_PV.js +575 -0
  71. package/dist/medterra-DnPN2ksU.cjs +575 -0
  72. package/dist/modells-Bmz8Ag5M.js +476 -0
  73. package/dist/modells-CoYgkLSp.cjs +476 -0
  74. package/dist/models-DHdb7QWn.js +51 -0
  75. package/dist/models-ixxUsGL_.cjs +69 -0
  76. package/dist/pressedFloral-DSKs_oVG.js +653 -0
  77. package/dist/pressedFloral-DjBiSoUl.cjs +653 -0
  78. package/dist/skinPerfection-B_3xzVNS.cjs +326 -0
  79. package/dist/skinPerfection-IDrBuAPt.js +326 -0
  80. package/dist/snapSupplements-BJk5T5ba.js +277 -0
  81. package/dist/snapSupplements-BStTsdOZ.cjs +277 -0
  82. package/dist/socialProofClasses-Bhv2Vulz.js +9 -0
  83. package/dist/socialProofClasses-CrQBWdSA.cjs +39 -0
  84. package/dist/spanx-BYg0LE7R.js +653 -0
  85. package/dist/spanx-LwU1zSzq.cjs +655 -0
  86. package/dist/spanxStaging-CfSmuKYB.js +837 -0
  87. package/dist/spanxStaging-OZLV9qix.cjs +840 -0
  88. package/dist/suggestionBarV2-types-BllzwsBD.js +34 -0
  89. package/dist/suggestionBarV2-types-CaovchMP.cjs +46 -0
  90. package/dist/supergoop-BqPXDnKk.cjs +327 -0
  91. package/dist/supergoop-CIlrHND_.js +325 -0
  92. package/dist/types-C4T5UOIW.cjs +230 -0
  93. package/dist/types-CYNvLeSA.js +176 -0
  94. package/dist/uniqueVintage-B30mOqbH.cjs +1205 -0
  95. package/dist/uniqueVintage-CFueJOhO.js +1203 -0
  96. package/dist/venaCbd-DHGZy49P.cjs +357 -0
  97. package/dist/venaCbd-T0CqVD4k.js +357 -0
  98. package/dist/westonJonBoucher-BdMzs_Yg.cjs +414 -0
  99. package/dist/westonJonBoucher-b4TCQ4ev.js +414 -0
  100. package/dist/wineEnthusiast-BLGlOjgr.cjs +932 -0
  101. package/dist/wineEnthusiast-BqR0i_54.js +932 -0
  102. package/dist/wolfMattress-CyyO-LoC.js +362 -0
  103. package/dist/wolfMattress-DNGZOivg.cjs +362 -0
  104. package/dist/wolfTactical-3Mm2fvVF.js +341 -0
  105. package/dist/wolfTactical-BmXYlFjr.cjs +341 -0
  106. package/package.json +66 -0
  107. package/src/adapters/amplitude/amplitudeAdapter.ts +454 -0
  108. package/src/adapters/amplitude/index.ts +2 -0
  109. package/src/adapters/amplitude/stubAmplitudeAdapter.ts +34 -0
  110. package/src/adapters/spiffy/commerce/api.ts +596 -0
  111. package/src/adapters/spiffy/commerce/exceptions/sessionExceptions.ts +6 -0
  112. package/src/adapters/spiffy/commerce/exceptions/unsupportedProductExceptions.ts +6 -0
  113. package/src/adapters/spiffy/commerce/graphql.ts +184 -0
  114. package/src/application/config/generalStaticConfig.ts +37 -0
  115. package/src/application/logging/logger.ts +29 -0
  116. package/src/application/models/api/context.ts +4 -0
  117. package/src/application/models/api/generationParams.ts +4 -0
  118. package/src/application/models/api/nextMessageRequest.ts +11 -0
  119. package/src/application/models/api/orgAnalyticsConfig.ts +19 -0
  120. package/src/application/models/api/orgConfigResults.ts +40 -0
  121. package/src/application/models/api/organizationConfig.ts +12 -0
  122. package/src/application/models/api/response.ts +132 -0
  123. package/src/application/models/api/responseGenerics.ts +67 -0
  124. package/src/application/models/api/search.ts +26 -0
  125. package/src/application/models/api/suggestion.ts +4 -0
  126. package/src/application/models/api/supportedEventRequest.ts +8 -0
  127. package/src/application/models/api/userEvent.ts +101 -0
  128. package/src/application/models/cachedValue.ts +8 -0
  129. package/src/application/models/chatElementDisplayLocation.ts +22 -0
  130. package/src/application/models/clientDetails.ts +18 -0
  131. package/src/application/models/colorsConfig.ts +28 -0
  132. package/src/application/models/conversationalSearchIds.ts +5 -0
  133. package/src/application/models/dataLayer.ts +45 -0
  134. package/src/application/models/domMutationContinuation.ts +7 -0
  135. package/src/application/models/domObservationStrategy.ts +9 -0
  136. package/src/application/models/events.ts +5 -0
  137. package/src/application/models/featureGates.ts +23 -0
  138. package/src/application/models/frontendConfig.ts +14 -0
  139. package/src/application/models/googleAnalyticsEvents.ts +8 -0
  140. package/src/application/models/graphql/index.ts +2 -0
  141. package/src/application/models/graphql/queries/getMerchantColorsQuery.ts +37 -0
  142. package/src/application/models/graphql/queries/getMerchantFrontendConfigQuery.ts +103 -0
  143. package/src/application/models/graphql/queries/getMerchantOrgIdQuery.ts +11 -0
  144. package/src/application/models/guards/api/index.ts +12 -0
  145. package/src/application/models/guards/api/isApiFormResponse.ts +90 -0
  146. package/src/application/models/guards/api/isApiFormSubmittedResponseAttributes.ts +37 -0
  147. package/src/application/models/guards/api/isApiOrderResponseAttributes.ts +155 -0
  148. package/src/application/models/guards/api/isApiOrgConfigResults.ts +277 -0
  149. package/src/application/models/guards/api/isApiOrganizationConfig.ts +207 -0
  150. package/src/application/models/guards/api/isApiPDPEventAttributes.ts +21 -0
  151. package/src/application/models/guards/api/isApiPLPEventAttributes.ts +41 -0
  152. package/src/application/models/guards/api/isApiPageResponseAttributes.ts +21 -0
  153. package/src/application/models/guards/api/isApiProductResponseAttributes.ts +85 -0
  154. package/src/application/models/guards/api/isApiProductSearchAttributes.ts +23 -0
  155. package/src/application/models/guards/api/isApiProductSearchFilterAttributes.ts +15 -0
  156. package/src/application/models/guards/api/isApiQueryTypedEventAttributes.ts +4 -0
  157. package/src/application/models/guards/api/isApiResponse.ts +39 -0
  158. package/src/application/models/guards/api/isApiReviewResponseAttributes.ts +30 -0
  159. package/src/application/models/guards/api/isApiReviewRichInformation.ts +37 -0
  160. package/src/application/models/guards/api/isApiSearchEventAttributes.ts +28 -0
  161. package/src/application/models/guards/api/isApiSuggestion.ts +36 -0
  162. package/src/application/models/guards/api/isApiSuggestionClickedEventAttributes.ts +9 -0
  163. package/src/application/models/guards/api/isApiTextResponseAttributes.ts +9 -0
  164. package/src/application/models/guards/api/isApiUserEvent.ts +25 -0
  165. package/src/application/models/guards/graphQL/isGraphQLColorsConfig.ts +50 -0
  166. package/src/application/models/guards/isBaseEcommerceEvent.ts +17 -0
  167. package/src/application/models/guards/isGA4EcommerceEvent.ts +17 -0
  168. package/src/application/models/guards/isLegacyUAEcommerceEvent.ts +17 -0
  169. package/src/application/models/guards/isMobilePLPChatPlacementParameter.ts +11 -0
  170. package/src/application/models/guards/isSpanxTakeAQuizCtaParameter.ts +4 -0
  171. package/src/application/models/guards/isVariantInfo.ts +37 -0
  172. package/src/application/models/guards/utils.ts +43 -0
  173. package/src/application/models/index.ts +20 -0
  174. package/src/application/models/localStorageEventListener.ts +4 -0
  175. package/src/application/models/message.ts +146 -0
  176. package/src/application/models/mobilePLPChatPlacementParameter.ts +3 -0
  177. package/src/application/models/orgsEnum.ts +36 -0
  178. package/src/application/models/productExperiment.ts +5 -0
  179. package/src/application/models/spanxTakeAQuizCtaParameter.ts +4 -0
  180. package/src/application/models/spiffyWidgets.ts +16 -0
  181. package/src/application/models/supportedOrgs.ts +137 -0
  182. package/src/application/models/utilityTypes/camelCase.ts +87 -0
  183. package/src/application/models/utilityTypes/camelCasedPropertiesDeep.ts +80 -0
  184. package/src/application/models/utilityTypes/delimiterCase.ts +121 -0
  185. package/src/application/models/utilityTypes/delimiterCasedPropertiesDeep.ts +98 -0
  186. package/src/application/models/utilityTypes/index.ts +1 -0
  187. package/src/application/models/utilityTypes/internal.ts +93 -0
  188. package/src/application/models/utilityTypes/primitive.ts +8 -0
  189. package/src/application/models/utilityTypes/snakeCasedPropertiesDeep.ts +49 -0
  190. package/src/application/models/utilityTypes/splitWords.ts +76 -0
  191. package/src/application/models/utilityTypes/trim.ts +28 -0
  192. package/src/application/models/utilityTypes/unknownArray.ts +25 -0
  193. package/src/application/models/utils/snakeToCamelTransformer.ts +90 -0
  194. package/src/application/models/utils/stringToFulfillmentDisplayStatusEnumValue.ts +68 -0
  195. package/src/application/models/validators/validateGraphQLColorsConfig.ts +29 -0
  196. package/src/application/models/validators/validateGraphQLFrontendConfig.ts +594 -0
  197. package/src/application/models/validators/validateGraphQLOrgId.ts +7 -0
  198. package/src/application/models/validators/validateMobilePLPChatPlacementParameter.ts +14 -0
  199. package/src/application/models/validators/validateOrgConfigResults.ts +47 -0
  200. package/src/application/models/validators/validateOrganizationConfig.ts +37 -0
  201. package/src/application/models/validators/validateResponse.ts +187 -0
  202. package/src/application/models/validators/validateSuggestion.ts +16 -0
  203. package/src/application/models/validators/validateUserEvent.ts +110 -0
  204. package/src/application/models/variantInfo/index.ts +1 -0
  205. package/src/application/models/variantInfo/pageVisitInfo.ts +6 -0
  206. package/src/application/models/variantInfo/plpInfo.ts +3 -0
  207. package/src/application/models/variantInfo/productInfo.ts +5 -0
  208. package/src/application/models/variantInfo/variantInfo.ts +23 -0
  209. package/src/application/service/cachingService.ts +84 -0
  210. package/src/application/service/cdnService.ts +18 -0
  211. package/src/application/service/customerService/index.ts +8 -0
  212. package/src/application/service/customerService/providers/UnsupportedCustomerService.ts +15 -0
  213. package/src/application/service/customerService/types.ts +31 -0
  214. package/src/application/service/domMutationObserver.ts +320 -0
  215. package/src/application/service/domMutations/GridInsertionService.ts +123 -0
  216. package/src/application/service/domMutations/dataLayer/dataLayerEventsListener.ts +99 -0
  217. package/src/application/service/domMutations/domInsertionService.ts +90 -0
  218. package/src/application/service/domMutations/domMutationListener.ts +15 -0
  219. package/src/application/service/domMutations/domMutationListenerState.ts +52 -0
  220. package/src/application/service/domMutations/floatingChat/embeddedChatsPlacementsListener.ts +41 -0
  221. package/src/application/service/domMutations/gladly/gladlyListener.ts +61 -0
  222. package/src/application/service/domMutations/spiffy/orgs/common/kustomerVisibilityListener.ts +41 -0
  223. package/src/application/service/domMutations/spiffy/orgs/common/orgsCommonDataLayerListener.ts +119 -0
  224. package/src/application/service/environmentService.ts +51 -0
  225. package/src/application/service/featureFlagService.ts +130 -0
  226. package/src/application/service/kustomerIntegrationService.ts +111 -0
  227. package/src/application/service/localStorageService.ts +77 -0
  228. package/src/application/service/pageVariantService.ts +779 -0
  229. package/src/application/service/searchService.ts +140 -0
  230. package/src/application/service/sessionStorageService.ts +27 -0
  231. package/src/application/service/shopifyUrlService.ts +63 -0
  232. package/src/application/service/userIdentityService.ts +114 -0
  233. package/src/application/service/windowChatToggleService.ts +71 -0
  234. package/src/application/service/windowDataLayerService.ts +181 -0
  235. package/src/application/service/windowFrontendConfigService.ts +104 -0
  236. package/src/application/utils/__tests__/divideArrays.test.ts +14 -0
  237. package/src/application/utils/analyticsUtils.ts +110 -0
  238. package/src/application/utils/coreContextToApiContext.ts +11 -0
  239. package/src/application/utils/coreUserEventToApiUserEvent.ts +106 -0
  240. package/src/application/utils/divideArray.ts +7 -0
  241. package/src/application/utils/domObserver.ts +96 -0
  242. package/src/application/utils/elementObserver.ts +246 -0
  243. package/src/application/utils/imageFilter.ts +12 -0
  244. package/src/application/utils/index.ts +3 -0
  245. package/src/application/utils/merchantUtils.ts +16 -0
  246. package/src/application/utils/messageFromFormSubmittedEvent.ts +31 -0
  247. package/src/application/utils/messageFromQueryEvent.ts +38 -0
  248. package/src/application/utils/messageFromResponse.ts +133 -0
  249. package/src/application/utils/messageFromSuggestionEvent.ts +32 -0
  250. package/src/application/utils/mouseEventTypes.ts +1 -0
  251. package/src/application/utils/mutationHelper.ts +51 -0
  252. package/src/application/utils/nextMessageRequestToApiRequest.ts +31 -0
  253. package/src/application/utils/nodeSelector.ts +133 -0
  254. package/src/application/utils/overrides.ts +196 -0
  255. package/src/application/utils/stringUtils.ts +55 -0
  256. package/src/application/utils/supportedEventRequestToApiRequest.ts +12 -0
  257. package/src/application/utils/urlsParser.ts +53 -0
  258. package/src/application/utils/validation.ts +5 -0
  259. package/src/atoms/app/index.ts +57 -0
  260. package/src/atoms/app/variant.ts +261 -0
  261. package/src/atoms/atomStore.ts +34 -0
  262. package/src/atoms/chat/chatState.ts +44 -0
  263. package/src/atoms/chat/form.ts +19 -0
  264. package/src/atoms/chat/index.ts +38 -0
  265. package/src/atoms/chat/lastMessage.ts +11 -0
  266. package/src/atoms/chat/messageQueue.ts +65 -0
  267. package/src/atoms/chat/performanceMetrics.ts +84 -0
  268. package/src/atoms/chat/renderedWidgetRefs.ts +28 -0
  269. package/src/atoms/chat/replies.ts +51 -0
  270. package/src/atoms/chat/suggestions.ts +36 -0
  271. package/src/atoms/globalSearch.ts +12 -0
  272. package/src/atoms/index.ts +5 -0
  273. package/src/atoms/org/customerService.ts +13 -0
  274. package/src/atoms/org/graphqlConfig.ts +27 -0
  275. package/src/atoms/org/index.ts +7 -0
  276. package/src/atoms/org/merchantCss.ts +44 -0
  277. package/src/atoms/org/org.ts +256 -0
  278. package/src/atoms/org/orgAnalyticsConfig.ts +28 -0
  279. package/src/atoms/org/orgPageConfig.ts +38 -0
  280. package/src/atoms/org/orgUIConfig.ts +122 -0
  281. package/src/atoms/search/chatSearch.ts +293 -0
  282. package/src/atoms/search/index.ts +2 -0
  283. package/src/atoms/search/productFilters.ts +207 -0
  284. package/src/atoms/search/productSorter.ts +23 -0
  285. package/src/atoms/search/searchAPI.ts +194 -0
  286. package/src/atoms/search/types.ts +55 -0
  287. package/src/atoms/search/utils.ts +18 -0
  288. package/src/config/divIds.ts +27 -0
  289. package/src/config/locators/components/chat/entrypoints.ts +13 -0
  290. package/src/config/locators/components/chat/index.ts +23 -0
  291. package/src/config/locators/components/chat/preview.ts +13 -0
  292. package/src/config/locators/components/chat/variants/index.ts +16 -0
  293. package/src/config/locators/components/common/buttons.ts +6 -0
  294. package/src/config/locators/components/common/cards.ts +18 -0
  295. package/src/config/locators/components/common/links.ts +1 -0
  296. package/src/config/locators/components/common/tables.ts +2 -0
  297. package/src/config/locators/components/floating-button.ts +2 -0
  298. package/src/config/locators/components/index.ts +3 -0
  299. package/src/config/locators/components/report-issue.ts +21 -0
  300. package/src/config/locators/components/search/index.ts +5 -0
  301. package/src/config/locators/components/shadow-dom.ts +1 -0
  302. package/src/config/locators/embedded.ts +21 -0
  303. package/src/config/locators/index.ts +3 -0
  304. package/src/config/socialProofClasses.ts +17 -0
  305. package/src/contexts/chatContext.tsx +451 -0
  306. package/src/contexts/enviveConfigContext.tsx +70 -0
  307. package/src/contexts/index.ts +4 -0
  308. package/src/contexts/systemSettingsContext.tsx +61 -0
  309. package/src/contexts/types.ts +1059 -0
  310. package/src/enabled-features.ts +83 -0
  311. package/src/events/event-types.ts +11 -0
  312. package/src/events/index.ts +52 -0
  313. package/src/events/registerAnalyticsListeners.ts +49 -0
  314. package/src/extension.ts +63 -0
  315. package/src/hooks/index.ts +22 -0
  316. package/src/hooks/useBlockBackButton.ts +29 -0
  317. package/src/hooks/useChatToggle.ts +66 -0
  318. package/src/hooks/useCustomerSupportHandoff.ts +39 -0
  319. package/src/hooks/useDebounce.ts +17 -0
  320. package/src/hooks/useDynamicVariants.ts +210 -0
  321. package/src/hooks/useElementObserver.ts +245 -0
  322. package/src/hooks/useFileUpload.ts +61 -0
  323. package/src/hooks/useGrabAndScroll.ts +133 -0
  324. package/src/hooks/useHideElements.ts +82 -0
  325. package/src/hooks/useHorizontalScrollAnimation.ts +115 -0
  326. package/src/hooks/useImageResolver.ts +51 -0
  327. package/src/hooks/useIntersection.ts +28 -0
  328. package/src/hooks/useIsSmallScreen.ts +23 -0
  329. package/src/hooks/useMessageFilter.ts +49 -0
  330. package/src/hooks/useMessageScrollObserver.ts +47 -0
  331. package/src/hooks/useReducedMotionWithOverride.ts +15 -0
  332. package/src/hooks/useSearch.tsx +433 -0
  333. package/src/hooks/useSnapCalculator.ts +38 -0
  334. package/src/hooks/useSnapControl.ts +155 -0
  335. package/src/hooks/useSystemSettingsContext.ts +12 -0
  336. package/src/hooks/useTrackComponentVisibleEvent.ts +52 -0
  337. package/src/hooks/useUpdateAnalyticsProps.ts +56 -0
  338. package/src/hooks/utils.ts +153 -0
  339. package/src/index.ts +31 -0
  340. package/src/initialize.ts +163 -0
  341. package/src/interceptors/types.ts +6 -0
  342. package/src/interceptors/useFormEscalation.ts +40 -0
  343. package/src/interceptors/useMessageInterceptor.ts +32 -0
  344. package/src/main.ts +85 -0
  345. package/src/main.tsx +123 -0
  346. package/src/merchants/bandolier/bandolier.ts +1389 -0
  347. package/src/merchants/carpe/carpe.ts +656 -0
  348. package/src/merchants/coterie/coterie.ts +280 -0
  349. package/src/merchants/default.ts +193 -0
  350. package/src/merchants/dreamlandBaby/dreamlandBaby.ts +375 -0
  351. package/src/merchants/fiveCbd/fiveCbd.ts +697 -0
  352. package/src/merchants/forLoveAndLemons/forLoveAndLemons.ts +721 -0
  353. package/src/merchants/greenpan/greenpan.ts +440 -0
  354. package/src/merchants/grooveLife/grooveLife.ts +386 -0
  355. package/src/merchants/homegrownCannabis/homegrownCannabis.ts +468 -0
  356. package/src/merchants/init-merchant.sh +53 -0
  357. package/src/merchants/jackArcher/jackArcher.ts +974 -0
  358. package/src/merchants/jordanCraig/jordanCraig.ts +1927 -0
  359. package/src/merchants/kindredBravely/kindredBravely.ts +529 -0
  360. package/src/merchants/kutFromTheKloth/kutFromTheKloth.ts +418 -0
  361. package/src/merchants/larryAndSerges/larryAndSerges.ts +314 -0
  362. package/src/merchants/leapsAndRebounds/leapsAndRebounds.ts +424 -0
  363. package/src/merchants/longevityrx/longevityrx.ts +368 -0
  364. package/src/merchants/lookOptic/lookOptic.ts +323 -0
  365. package/src/merchants/mantraBrand/mantraBrand.ts +838 -0
  366. package/src/merchants/medterra/medterra.ts +670 -0
  367. package/src/merchants/modells/modells.ts +546 -0
  368. package/src/merchants/pressedFloral/pressedFloral.ts +734 -0
  369. package/src/merchants/skinPerfection/skinPerfection.ts +379 -0
  370. package/src/merchants/snapSupplements/snapSupplements.ts +325 -0
  371. package/src/merchants/spanx/spanx.ts +810 -0
  372. package/src/merchants/spanx/spanxStaging.ts +942 -0
  373. package/src/merchants/supergoop/supergoop.ts +376 -0
  374. package/src/merchants/uniqueVintage/uniqueVintage.ts +1314 -0
  375. package/src/merchants/uniqueVintage/views/useUniqueVintageChatSearch.ts +147 -0
  376. package/src/merchants/venaCbd/venaCbd.ts +410 -0
  377. package/src/merchants/westonJonBoucher/westonJonBoucher.ts +473 -0
  378. package/src/merchants/wineEnthusiast/wineEnthusiast.ts +990 -0
  379. package/src/merchants/wolfMattress/wolfMattress.ts +411 -0
  380. package/src/merchants/wolfTactical/wolfTactical.ts +389 -0
  381. package/src/types/custservice-types.ts +28 -0
  382. package/src/types/search-filter-types.ts +111 -0
  383. package/src/types/suggestionBarV2-types.ts +4 -0
  384. package/src/types/test-types.ts +3 -0
  385. package/src/types.ts +66 -0
@@ -0,0 +1,12 @@
1
+ import { Message, MessageType, ProductMessageMetadata } from 'src/application/models';
2
+
3
+ export const getRecentProductImageUrls = (lastMessages: Message[], currentProductId: string | undefined) => {
4
+ const productMessages = lastMessages
5
+ .filter((message) => message.type === MessageType.Product && message.metadata?.imageUrl)
6
+ .map((m) => m as ProductMessageMetadata);
7
+ // put added product image at the top of the list
8
+ return [
9
+ ...productMessages.filter((m) => m.metadata?.id === currentProductId),
10
+ ...productMessages.filter((m) => m.metadata?.id !== currentProductId),
11
+ ].map((m) => m.metadata!.imageUrl!);
12
+ };
@@ -0,0 +1,3 @@
1
+ export * from './messageFromQueryEvent';
2
+ export * from './messageFromResponse';
3
+ export * from './messageFromSuggestionEvent';
@@ -0,0 +1,16 @@
1
+ export const prepareMerchantPage = () => {
2
+ let metaViewport = document.querySelector("meta[name='viewport']");
3
+ if (metaViewport) {
4
+ const content = metaViewport.getAttribute("content")
5
+ const hasMaximumScale = content?.includes("maximum-scale=1")
6
+ if (!hasMaximumScale) {
7
+ metaViewport.setAttribute("content", `${content}, maximum-scale=1`)
8
+ }
9
+ return
10
+ }
11
+
12
+ metaViewport = document.createElement("meta");
13
+ metaViewport.setAttribute("name", "viewport")
14
+ metaViewport.setAttribute("content", "width=device-width, initial-scale=1, maximum-scale=1")
15
+ document.head.appendChild(metaViewport);
16
+ }
@@ -0,0 +1,31 @@
1
+ import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
2
+ import {
3
+ FormResponseAttributes,
4
+ Message,
5
+ MessageRole,
6
+ MessageType,
7
+ UserEvent,
8
+ } from 'src/application/models';
9
+
10
+ export const messageFromFormSubmittedEvent = (
11
+ event: UserEvent,
12
+ formResponseAttributes: FormResponseAttributes['attributes'],
13
+ ): Message | undefined => {
14
+ if (event.category !== UserEventCategory.FormSubmitted) {
15
+ return undefined;
16
+ }
17
+
18
+ const formStringContents = Object.entries(formResponseAttributes.schema.properties)
19
+ .map(([key, value]) => `${value.title}: ${event.attributes.filledSchema[key]}`)
20
+ .join('\n');
21
+
22
+ return {
23
+ id: event.eventId,
24
+ role: MessageRole.User,
25
+ type: MessageType.QueryTyped,
26
+ createdAt: event.createdAt,
27
+ metadata: {
28
+ content: formStringContents,
29
+ },
30
+ };
31
+ };
@@ -0,0 +1,38 @@
1
+ import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
2
+ import { Message, MessageRole, MessageType, UserEvent } from 'src/application/models';
3
+
4
+ /**
5
+ * Transforms a query UserEvent object into a Message object for presentation.
6
+ *
7
+ * @param event The user event object received from the server
8
+ *
9
+ * @returns A Message if the event is a query event, otherwise undefined
10
+ */
11
+ export const messageFromQueryEvent = (event: UserEvent): Message | undefined => {
12
+ if (event.category === UserEventCategory.QueryTyped) {
13
+ return {
14
+ id: event.eventId,
15
+ role: MessageRole.User,
16
+ type: MessageType.QueryTyped,
17
+ createdAt: event.createdAt,
18
+ metadata: {
19
+ content: event.attributes.query,
20
+ },
21
+ };
22
+ }
23
+
24
+ if (event.category === UserEventCategory.Search) {
25
+ return {
26
+ id: event.eventId,
27
+ role: MessageRole.User,
28
+ type: MessageType.Search,
29
+ createdAt: event.createdAt,
30
+ metadata: {
31
+ searchTerm: event.attributes.searchTerm || '',
32
+ selectedFilters: event.attributes.selectedFilters || [],
33
+ },
34
+ };
35
+ }
36
+
37
+ return undefined;
38
+ };
@@ -0,0 +1,133 @@
1
+ import { ResponseCategory } from '@spiffy-ai/commerce-api-client';
2
+ import { Message, MessageRole, MessageType, Response } from 'src/application/models';
3
+
4
+ /**
5
+ * Transforms a server Response object into a Message object for presentation.
6
+ *
7
+ * @param response The response object received from the server containing model generated content
8
+ *
9
+ * @returns A Message if the response contains known attributes, undefined otherwise
10
+ */
11
+ export const messageFromResponse = (response?: Response): Message | undefined => {
12
+ if (response == null) {
13
+ return undefined;
14
+ }
15
+
16
+ if (response.category === ResponseCategory.Text) {
17
+ return {
18
+ id: response.id,
19
+ createdAt: response.createdAt,
20
+ type: MessageType.Text,
21
+ role: MessageRole.Assistant,
22
+ metadata: {
23
+ content: response.attributes.content,
24
+ },
25
+ };
26
+ }
27
+
28
+ if (response.category === ResponseCategory.Product) {
29
+ return {
30
+ id: response.id,
31
+ createdAt: response.createdAt,
32
+ role: MessageRole.Assistant,
33
+ type: MessageType.Product,
34
+ metadata: {
35
+ ...response.attributes,
36
+ },
37
+ };
38
+ }
39
+
40
+ if (response.category === ResponseCategory.Review) {
41
+ return {
42
+ id: response.id,
43
+ createdAt: response.createdAt,
44
+ type: MessageType.Review,
45
+ role: MessageRole.Assistant,
46
+ metadata: {
47
+ review: response.attributes.review,
48
+ reviewer: response.attributes.reviewer,
49
+ stars: response.attributes.stars,
50
+ title: response.attributes.title,
51
+ richInformation: response.attributes.richInformation,
52
+ },
53
+ };
54
+ }
55
+
56
+ if (response.category === ResponseCategory.Separator) {
57
+ return {
58
+ id: response.id,
59
+ createdAt: response.createdAt,
60
+ type: MessageType.Separator,
61
+ role: MessageRole.Assistant,
62
+ };
63
+ }
64
+
65
+ if (response.category === ResponseCategory.Page) {
66
+ return {
67
+ id: response.id,
68
+ createdAt: response.createdAt,
69
+ role: MessageRole.Assistant,
70
+ type: MessageType.Page,
71
+ metadata: {
72
+ ...response.attributes,
73
+ },
74
+ };
75
+ }
76
+
77
+ if (response.category === ResponseCategory.ProductSearch) {
78
+ return {
79
+ id: response.id,
80
+ createdAt: response.createdAt,
81
+ role: MessageRole.Assistant,
82
+ type: MessageType.ProductSearch,
83
+ metadata: {
84
+ ...response.attributes,
85
+ },
86
+ };
87
+ }
88
+
89
+ if (response.category === ResponseCategory.ProductSearchFilter) {
90
+ return {
91
+ id: response.id,
92
+ createdAt: response.createdAt,
93
+ role: MessageRole.Assistant,
94
+ type: MessageType.ProductSearchFilter,
95
+ metadata: {
96
+ ...response.attributes,
97
+ },
98
+ };
99
+ }
100
+
101
+ if (response.category === ResponseCategory.Form) {
102
+ return {
103
+ id: response.id,
104
+ createdAt: response.createdAt,
105
+ role: MessageRole.Assistant,
106
+ type: MessageType.Form,
107
+ metadata: {
108
+ formType: response.attributes.formCategory?.formType,
109
+ fields: Object.entries(response.attributes.schema.properties).map(([key, value]) => ({
110
+ key,
111
+ title: value.title,
112
+ type: value.type,
113
+ format: value.format,
114
+ required: response.attributes.schema.required.includes(key),
115
+ })),
116
+ },
117
+ };
118
+ }
119
+
120
+ if (response.category === ResponseCategory.Order) {
121
+ return {
122
+ id: response.id,
123
+ createdAt: response.createdAt,
124
+ role: MessageRole.Assistant,
125
+ type: MessageType.Order,
126
+ metadata: {
127
+ ...response.attributes,
128
+ },
129
+ };
130
+ }
131
+
132
+ return undefined;
133
+ };
@@ -0,0 +1,32 @@
1
+ import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
2
+ import { Message, MessageRole, MessageType, Suggestion, UserEvent } from 'src/application/models';
3
+
4
+ /**
5
+ * Transforms a UserEvent object into a Message object for presentation.
6
+ *
7
+ * @param event The UserEvent object received from the server
8
+ * @param suggestions A list of generated suggestions to match the event to
9
+ *
10
+ * @returns A Message if the event is a suggestion click event, undefined otherwise
11
+ */
12
+ export const messageFromSuggestionEvent = (
13
+ event: UserEvent,
14
+ suggestions: Suggestion[],
15
+ ): Message | undefined => {
16
+ if (event.category === UserEventCategory.SuggestionClicked) {
17
+ const { suggestionId } = event.attributes;
18
+
19
+ return {
20
+ id: event.eventId,
21
+ role: MessageRole.User,
22
+ type: MessageType.SuggestionClicked,
23
+ createdAt: event.createdAt,
24
+ metadata: {
25
+ suggestionId,
26
+ suggestionContent: suggestions.find((s) => s.id === suggestionId)?.content ?? '',
27
+ },
28
+ };
29
+ }
30
+
31
+ return undefined;
32
+ };
@@ -0,0 +1 @@
1
+ export type MouseEventTypes = 'click' | 'dblclick' | 'mouseup' | 'mousedown';
@@ -0,0 +1,51 @@
1
+ const compareTokens = (original: string, comparison: string) => {
2
+ const originalTokens = new Set(original.split(' '));
3
+ const comparisonTokens = new Set(comparison.split(' '));
4
+ return [...originalTokens].filter((token) => !comparisonTokens.has(token));
5
+ };
6
+
7
+ export class MutationHelper {
8
+ static fireClassChange(
9
+ record: MutationRecord,
10
+ node: HTMLElement | null,
11
+ fn: (classes: DOMTokenList) => void,
12
+ ) {
13
+ if (node && record.oldValue !== node?.classList.value) {
14
+ fn(node?.classList);
15
+ }
16
+ }
17
+
18
+ static fireClassAdded(
19
+ record: MutationRecord,
20
+ node: HTMLElement | null,
21
+ classMap: Map<string, () => void>,
22
+ ) {
23
+ if (node && record.oldValue) {
24
+ const tokens = compareTokens(node?.classList.value, record.oldValue);
25
+ tokens.forEach((className) => classMap.get(className)?.());
26
+ }
27
+ }
28
+
29
+ static fireClassRemoved(
30
+ record: MutationRecord,
31
+ node: HTMLElement | null,
32
+ classMap: Map<string, () => void>,
33
+ ) {
34
+ if (node && record.oldValue) {
35
+ const tokens = compareTokens(record.oldValue, node?.classList.value);
36
+ tokens.forEach((className) => classMap.get(className)?.());
37
+ }
38
+ }
39
+
40
+ static fireSubtreeChange(nodes: NodeList, fn?: (nodes: NodeList) => void) {
41
+ nodes.length && fn?.(nodes);
42
+ }
43
+
44
+ static isClass(mutation: MutationRecord) {
45
+ return mutation.type === 'attributes' && mutation.attributeName === 'class';
46
+ }
47
+
48
+ static isChildList(mutation: MutationRecord) {
49
+ return mutation.type === 'childList';
50
+ }
51
+ }
@@ -0,0 +1,31 @@
1
+ import { NextMessageRequest as ApiNextMessageRequest } from '@spiffy-ai/commerce-api-client';
2
+ import { NextMessageRequest } from '../models';
3
+ import { coreUserEventToApiUserEvent } from './coreUserEventToApiUserEvent';
4
+
5
+ export const messageRequestToCommerceMessageRequest = (
6
+ data: NextMessageRequest,
7
+ ): ApiNextMessageRequest => ({
8
+ context: {
9
+ chat_id: data.context.chatId,
10
+ org_id: data.context.orgId,
11
+ org_short_name: data.context.orgShortName,
12
+ user_id: data.context.userId,
13
+ source: data.context.source,
14
+ env: data.context.env,
15
+ },
16
+ id: data.id,
17
+ feature_flags: data.featureFlags,
18
+ user_events: data.userEvents?.map((userEvent) => coreUserEventToApiUserEvent(userEvent)),
19
+ generation_params: {
20
+ model: data.generationParams?.model,
21
+ max_tokens: data.generationParams?.maxTokens,
22
+ stop: data.generationParams?.stop,
23
+ stream: data.generationParams?.stream,
24
+ temperature: data.generationParams?.temperature,
25
+ top_p: data.generationParams?.topP,
26
+ num_suggestions: data.generationParams?.numSuggestions,
27
+ response_system_prompt: data.generationParams?.responseSystemPrompt,
28
+ suggestion_system_prompt: data.generationParams?.suggestionSystemPrompt,
29
+ response_caching: data.generationParams?.responseCaching,
30
+ },
31
+ });
@@ -0,0 +1,133 @@
1
+ export abstract class NodeSelector {
2
+ private pattern: string;
3
+ private root: Document;
4
+
5
+ constructor(pattern: string) {
6
+ this.pattern = pattern;
7
+ this.root = document;
8
+ }
9
+
10
+ getPattern() {
11
+ return this.pattern;
12
+ }
13
+
14
+ setRoot(root: Document) {
15
+ this.root = root;
16
+ }
17
+
18
+ getRoot() {
19
+ return this.root;
20
+ }
21
+
22
+ abstract parse(): Node | null;
23
+ }
24
+
25
+ class QuerySelector extends NodeSelector {
26
+ parse(): Node | null {
27
+ return this.getRoot().querySelector(this.getPattern());
28
+ }
29
+ }
30
+
31
+ class IDSelector extends NodeSelector {
32
+ parse(): Node | null {
33
+ return this.getRoot().getElementById(this.getPattern()) as Node;
34
+ }
35
+ }
36
+
37
+ class XpathSelector extends NodeSelector {
38
+ parse(): Node | null {
39
+ return this.getRoot()?.evaluate(
40
+ this.getPattern(),
41
+ this.getRoot(),
42
+ null,
43
+ XPathResult.FIRST_ORDERED_NODE_TYPE,
44
+ null,
45
+ )?.singleNodeValue as Node;
46
+ }
47
+ }
48
+
49
+ class ChainSelector extends NodeSelector {
50
+ parse(): Node | null {
51
+ let selectorIndex = 0;
52
+ const selectors = this.getPattern().split('@');
53
+ const lastIndex = selectors.length - 1;
54
+
55
+ const parseChain = (pattern: string, prevNode?: Node | null): Node | null => {
56
+ const selector = SelectorFactory.parse(pattern);
57
+
58
+ if (prevNode) {
59
+ selector.setRoot(prevNode as Document);
60
+ }
61
+
62
+ const currentNode = selector.parse();
63
+ if (selectorIndex === lastIndex) {
64
+ return currentNode;
65
+ }
66
+
67
+ let node: Node | null | undefined = currentNode || document;
68
+ if ((currentNode as HTMLElement)?.shadowRoot) {
69
+ node = (currentNode as HTMLElement).shadowRoot;
70
+ }
71
+
72
+ if ((currentNode as HTMLIFrameElement)?.contentWindow) {
73
+ node = (currentNode as HTMLIFrameElement).contentWindow?.document;
74
+ }
75
+
76
+ return parseChain(selectors[++selectorIndex].trim(), node);
77
+ };
78
+
79
+ return parseChain(selectors[selectorIndex].trim());
80
+ }
81
+ }
82
+
83
+ class Empty extends NodeSelector {
84
+ constructor() {
85
+ super('');
86
+ }
87
+ parse(): Node | null {
88
+ return null;
89
+ }
90
+ }
91
+
92
+ export class SelectorFactory {
93
+ static parse(composedSelector?: string) {
94
+ if (!composedSelector) {
95
+ return new Empty();
96
+ }
97
+
98
+ const split = composedSelector.split('|');
99
+ const type = split[0];
100
+ const selector = split[1];
101
+
102
+ switch (type) {
103
+ case 'id':
104
+ return this.id(selector);
105
+ case 'query':
106
+ return this.query(selector);
107
+ case 'xpath':
108
+ return this.xpath(selector);
109
+ default:
110
+ return new Empty();
111
+ }
112
+ }
113
+
114
+ static check(selector?: NodeSelector) {
115
+ return selector ?? new Empty();
116
+ }
117
+
118
+ static chain(pattern?: string) {
119
+ return pattern ? new ChainSelector(pattern) : new Empty();
120
+ }
121
+
122
+ static id(pattern?: string): NodeSelector {
123
+ return pattern ? new IDSelector(pattern) : new Empty();
124
+ }
125
+
126
+ static query(pattern?: string): NodeSelector {
127
+ return pattern ? new QuerySelector(pattern) : new Empty();
128
+ }
129
+
130
+ static xpath(pattern?: string): NodeSelector {
131
+ return pattern ? new XpathSelector(pattern) : new Empty();
132
+ }
133
+ }
@@ -0,0 +1,196 @@
1
+ export type ReplaceOp<T> = { $replace: T };
2
+ export type DeleteOp = { $delete: true };
3
+
4
+ // Treat these as atomic values (not recursed into)
5
+ type Builtin = Date | RegExp | ((...args: unknown[]) => unknown);
6
+
7
+ type Primitive = string | number | boolean | bigint | symbol | null | undefined;
8
+
9
+ /**
10
+ * Override<T> is a DeepPartial-like type with special operators:
11
+ * - { $replace: T } to replace an entire subtree/array
12
+ * - { $delete: true } to delete an object key
13
+ *
14
+ * Arrays behavior:
15
+ * - Arrays of objects: merge-by-index by default (unless `arrayStrategy: 'replace'` or `$replace` is used)
16
+ * - Arrays of primitives (string/number/boolean/...): replaced by default when a patch array is provided
17
+ */
18
+ export type Override<T> =
19
+ // atomic
20
+ T extends Primitive | Builtin
21
+ ? T | ReplaceOp<T> | DeleteOp
22
+ : // arrays
23
+ T extends (infer U)[]
24
+ ? Array<Override<U> | undefined> | ReplaceOp<T>
25
+ : // maps/sets – keep simple: only allow full replace
26
+ T extends Map<unknown, unknown> | Set<unknown>
27
+ ? ReplaceOp<T>
28
+ : // objects
29
+ T extends object
30
+ ? { [K in keyof T]?: Override<T[K]> | DeleteOp | null } | ReplaceOp<T>
31
+ : T;
32
+
33
+ export type MergeOptions = {
34
+ /**
35
+ * How to treat arrays when patch provides an array (not $replace):
36
+ * - 'replace': always use patch array as whole value
37
+ * - 'mergeByIndex': merge each index recursively (default for arrays of objects)
38
+ * Note: Arrays of primitives are replaced by default regardless of this option.
39
+ */
40
+ arrayStrategy?: 'replace' | 'mergeByIndex';
41
+ /**
42
+ * If true, a `null` patch value deletes the key from an object (RFC 7396-ish)
43
+ */
44
+ nullDeletes?: boolean;
45
+ };
46
+
47
+ // Prevents T from being inferred from the 'patch' parameter; it must be inferred from 'base'.
48
+ // See: https://github.com/microsoft/TypeScript/issues/14829#issuecomment-504042546
49
+ type NoInfer<T> = [T][T extends unknown ? 0 : never];
50
+
51
+ function isPlainObject(x: unknown): x is Record<string, unknown> {
52
+ return (
53
+ !!x &&
54
+ typeof x === 'object' &&
55
+ !Array.isArray(x) &&
56
+ !(x instanceof Date) &&
57
+ !(x instanceof RegExp)
58
+ );
59
+ }
60
+
61
+ function isReplace(x: unknown): x is ReplaceOp<unknown> {
62
+ return !!x && typeof x === 'object' && '$replace' in (x as Record<string, unknown>);
63
+ }
64
+ function isDelete(x: unknown): x is DeleteOp {
65
+ return !!x && typeof x === 'object' && (x as Record<string, unknown>).$delete === true;
66
+ }
67
+
68
+ function isPrimitiveValue(x: unknown): boolean {
69
+ const t = typeof x;
70
+ return (
71
+ x === null ||
72
+ t === 'string' ||
73
+ t === 'number' ||
74
+ t === 'boolean' ||
75
+ t === 'bigint' ||
76
+ t === 'symbol' ||
77
+ t === 'undefined'
78
+ );
79
+ }
80
+
81
+ function isArrayOfPrimitives(arr: unknown[]): boolean {
82
+ if (arr.length === 0) return false; // ambiguous, default to merge-by-index on empty
83
+ // If every defined element is primitive, treat as primitives
84
+ for (let i = 0; i < arr.length; i += 1) {
85
+ const v = arr[i];
86
+ if (v !== undefined && !isPrimitiveValue(v)) return false;
87
+ }
88
+ return true;
89
+ }
90
+
91
+ function mergeAny(baseAny: unknown, patchAny: unknown, opts: MergeOptions): unknown {
92
+ if (isReplace(patchAny)) return patchAny.$replace as unknown;
93
+ if (isDelete(patchAny)) return undefined; // caller deletes the key
94
+
95
+ if (Array.isArray(baseAny)) {
96
+ if (Array.isArray(patchAny)) {
97
+ const baseArr = baseAny as unknown[];
98
+ const patchArr = patchAny as unknown[];
99
+ const shouldReplace =
100
+ opts.arrayStrategy === 'replace' ||
101
+ isArrayOfPrimitives(baseArr) ||
102
+ isArrayOfPrimitives(patchArr);
103
+ if (shouldReplace) return patchAny as unknown;
104
+ const out = baseArr.slice();
105
+ const max = Math.max(out.length, patchArr.length);
106
+ for (let i = 0; i < max; i += 1) {
107
+ const pVal = patchArr[i];
108
+ if (pVal !== undefined) {
109
+ out[i] = mergeAny(out[i], pVal, opts);
110
+ }
111
+ }
112
+ return out as unknown;
113
+ }
114
+ return baseAny as unknown;
115
+ }
116
+
117
+ if (isPlainObject(baseAny) && isPlainObject(patchAny)) {
118
+ const baseObj = baseAny as Record<string, unknown>;
119
+ const patchObj = patchAny as Record<string, unknown>;
120
+ const out: Record<string, unknown> = { ...baseObj };
121
+ for (const key of Object.keys(patchObj)) {
122
+ const pVal = patchObj[key];
123
+ if (pVal === undefined) {
124
+ // leave as-is
125
+ } else if (opts.nullDeletes && pVal === null) {
126
+ delete out[key];
127
+ } else if (isReplace(pVal)) {
128
+ out[key] = pVal.$replace;
129
+ } else if (isDelete(pVal)) {
130
+ delete out[key];
131
+ } else {
132
+ out[key] = mergeAny(baseObj?.[key], pVal, opts);
133
+ }
134
+ }
135
+ return out as unknown;
136
+ }
137
+
138
+ return (patchAny as unknown) ?? baseAny;
139
+ }
140
+
141
+ export function applyOverrides<T>(
142
+ base: T,
143
+ patch: Override<NoInfer<T>>,
144
+ opts: MergeOptions = {},
145
+ ): T {
146
+ const { arrayStrategy = 'mergeByIndex', nullDeletes = false } = opts;
147
+
148
+ // Handle whole-node control operators on patch itself
149
+ if (isReplace(patch)) return patch.$replace as T;
150
+ if (isDelete(patch)) return undefined as unknown as T;
151
+
152
+ // Arrays
153
+ if (Array.isArray(base)) {
154
+ if (isReplace(patch)) return patch.$replace as T;
155
+ if (Array.isArray(patch)) {
156
+ if (arrayStrategy === 'replace') return patch as unknown as T;
157
+ // merge by index
158
+ const out = (base as unknown[]).slice();
159
+ const max = Math.max(out.length, patch.length);
160
+ for (let i = 0; i < max; i += 1) {
161
+ const pVal = (patch as unknown[])[i];
162
+ if (pVal !== undefined) {
163
+ out[i] = mergeAny(out[i], pVal, opts);
164
+ }
165
+ }
166
+ return out as unknown as T;
167
+ }
168
+ // invalid patch type for an array → ignore and return base
169
+ return base as T;
170
+ }
171
+
172
+ // Plain objects
173
+ if (isPlainObject(base) && isPlainObject(patch)) {
174
+ const out: Record<string, unknown> = { ...(base as Record<string, unknown>) };
175
+ const patchObj = patch as Record<string, unknown>;
176
+ for (const key of Object.keys(patchObj)) {
177
+ const pVal = patchObj[key];
178
+ if (pVal === undefined) {
179
+ // leave existing value
180
+ } else if (nullDeletes && pVal === null) {
181
+ delete out[key];
182
+ } else if (isReplace(pVal)) {
183
+ out[key] = pVal.$replace;
184
+ } else if (isDelete(pVal)) {
185
+ delete out[key];
186
+ } else {
187
+ const bVal = (base as Record<string, unknown>)[key];
188
+ out[key] = mergeAny(bVal, pVal, opts);
189
+ }
190
+ }
191
+ return out as unknown as T;
192
+ }
193
+
194
+ // For primitives or when patch is primitive, patch wins if defined
195
+ return ((patch as unknown) ?? base) as T;
196
+ }