@faststore/core 3.99.0 → 4.0.0-dev.1

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 (543) hide show
  1. package/.turbo/turbo-generate.log +29 -0
  2. package/.turbo/turbo-test.log +47 -16
  3. package/@generated/cached-operations.json +24 -0
  4. package/@generated/gql.ts +134 -210
  5. package/@generated/graphql.ts +1628 -3037
  6. package/@generated/index.ts +1 -1
  7. package/@generated/persisted-documents.json +1 -1
  8. package/@generated/schema.graphql +1854 -1743
  9. package/CHANGELOG.md +12 -2
  10. package/README.md +2 -1
  11. package/api/index.ts +6 -7
  12. package/cms/faststore/base.jsonc +1 -1
  13. package/cms/faststore/components/cms_component__alert.jsonc +5 -1
  14. package/cms/faststore/components/cms_component__bannernewsletter.jsonc +5 -1
  15. package/cms/faststore/components/cms_component__bannertext.jsonc +5 -1
  16. package/cms/faststore/components/cms_component__breadcrumb.jsonc +16 -4
  17. package/cms/faststore/components/cms_component__cartsidebar.jsonc +21 -1
  18. package/cms/faststore/components/cms_component__children.jsonc +5 -1
  19. package/cms/faststore/components/cms_component__crosssellingshelf.jsonc +5 -1
  20. package/cms/faststore/components/cms_component__emptystate.jsonc +8 -3
  21. package/cms/faststore/components/cms_component__footer.jsonc +9 -3
  22. package/cms/faststore/components/cms_component__hero.jsonc +5 -1
  23. package/cms/faststore/components/cms_component__incentives.jsonc +5 -1
  24. package/cms/faststore/components/cms_component__navbar.jsonc +139 -1
  25. package/cms/faststore/components/cms_component__newsletter.jsonc +5 -1
  26. package/cms/faststore/components/cms_component__productdetails.jsonc +33 -1
  27. package/cms/faststore/components/cms_component__productgallery.jsonc +113 -15
  28. package/cms/faststore/components/cms_component__productshelf.jsonc +5 -1
  29. package/cms/faststore/components/cms_component__producttiles.jsonc +5 -1
  30. package/cms/faststore/components/cms_component__regionbar.jsonc +5 -1
  31. package/cms/faststore/components/cms_component__regionmodal.jsonc +5 -1
  32. package/cms/faststore/components/cms_component__regionpopover.jsonc +5 -1
  33. package/cms/faststore/components/cms_component__scrolltotopbutton.jsonc +29 -0
  34. package/cms/faststore/components/cms_component__search.jsonc +5 -1
  35. package/cms/faststore/content-types.json +115 -0
  36. package/cms/faststore/pages/cms_content_type__globalsections.jsonc +52 -0
  37. package/cms/faststore/pages/cms_content_type__home.jsonc +6 -0
  38. package/cms/faststore/pages/cms_content_type__landingpage.jsonc +8 -1
  39. package/cms/faststore/pages/cms_content_type__pdp.jsonc +6 -0
  40. package/cms/faststore/pages/cms_content_type__plp.jsonc +17 -0
  41. package/cms/faststore/pages/cms_content_type__search.jsonc +17 -0
  42. package/cms/faststore/schema.json +547 -43
  43. package/cms/faststore/sections.json +330 -21
  44. package/discovery.config.default.js +49 -3
  45. package/next-env.d.ts +2 -1
  46. package/next.config.js +48 -26
  47. package/package.json +47 -60
  48. package/public/icons.svg +5 -1
  49. package/scripts/i18n.js +76 -0
  50. package/src/components/account/MyAccountDrawer/OrganizationDrawer/OrganizationDrawer.tsx +2 -1
  51. package/src/components/account/MyAccountDrawer/OrganizationDrawer/section.module.scss +25 -24
  52. package/src/components/account/MyAccountDrawer/ProfileSummary/profile-summary.scss +8 -6
  53. package/src/components/account/MyAccountLayout/styles.scss +16 -12
  54. package/src/components/account/MyAccountMenu/styles.scss +21 -22
  55. package/src/components/account/MyAccountUserDetails/styles.module.scss +4 -2
  56. package/src/components/account/components/MyAccountAccordion/styles.scss +4 -2
  57. package/src/components/account/components/MyAccountHeader/styles.scss +3 -1
  58. package/src/components/account/components/MyAccountTable/styles.scss +6 -4
  59. package/src/components/account/orders/MyAccountListOrders/MyAccountFilterSlider/section.module.scss +21 -19
  60. package/src/components/account/orders/MyAccountListOrders/MyAccountListOrdersTable/MyAccountListOrdersTable.tsx +3 -1
  61. package/src/components/account/orders/MyAccountListOrders/MyAccountListOrdersTable/styles.scss +5 -3
  62. package/src/components/account/orders/MyAccountListOrders/styles.module.scss +25 -22
  63. package/src/components/account/orders/MyAccountOrderDetails/MyAccountBudgetsCard/styles.scss +7 -5
  64. package/src/components/account/orders/MyAccountOrderDetails/MyAccountDeliveryOptionAccordion/styles.scss +7 -5
  65. package/src/components/account/orders/MyAccountOrderDetails/MyAccountMoreInformationCard/styles.scss +3 -1
  66. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActionModal/styles.module.scss +8 -6
  67. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActions/styles.scss +3 -1
  68. package/src/components/account/orders/MyAccountOrderDetails/MyAccountStatusCard/styles.scss +8 -6
  69. package/src/components/account/orders/MyAccountOrderDetails/section.module.scss +36 -43
  70. package/src/components/account/profile/profile.module.scss +3 -1
  71. package/src/components/account/section.module.scss +3 -1
  72. package/src/components/account/security/styles.module.scss +14 -8
  73. package/src/components/cart/CartSidebar/CartSidebar.tsx +10 -1
  74. package/src/components/cart/CartSidebar/section.module.scss +19 -17
  75. package/src/components/cart/EmptyCart/EmptyCart.tsx +12 -4
  76. package/src/components/cms/GlobalSections.tsx +12 -12
  77. package/src/components/cms/RenderSections.tsx +10 -2
  78. package/src/components/cms/plp/Components.ts +9 -0
  79. package/src/components/common/Alert/section.module.scss +10 -5
  80. package/src/components/common/PreviewTag/section.module.scss +48 -40
  81. package/src/components/common/Toast/section.module.scss +4 -2
  82. package/src/components/localization/LocalizationSelector/LocalizationSelector.tsx +320 -0
  83. package/src/components/localization/LocalizationSelector/index.ts +1 -0
  84. package/src/components/localization/LocalizationSelector/section.module.scss +18 -0
  85. package/src/components/localization/index.ts +1 -0
  86. package/src/components/navigation/Navbar/Navbar.tsx +49 -1
  87. package/src/components/navigation/NavbarSlider/NavbarSlider.tsx +19 -1
  88. package/src/components/navigation/NavbarSlider/section.module.scss +12 -10
  89. package/src/components/product/OutOfStock/OutOfStock.tsx +6 -1
  90. package/src/components/product/ProductCard/ProductCard.tsx +1 -1
  91. package/src/components/region/RegionModal/RegionModal.tsx +4 -1
  92. package/src/components/region/RegionModal/section.module.scss +10 -8
  93. package/src/components/region/RegionPopover/RegionPopover.tsx +6 -5
  94. package/src/components/region/RegionPopover/section.module.scss +9 -7
  95. package/src/components/region/RegionSlider/RegionSlider.tsx +5 -2
  96. package/src/components/region/RegionSlider/section.module.scss +16 -13
  97. package/src/components/search/Filter/FilterDeliveryMethodFacet.tsx +5 -5
  98. package/src/components/search/Filter/FilterDesktop.tsx +13 -4
  99. package/src/components/search/Filter/FilterSlider.tsx +18 -6
  100. package/src/components/search/Filter/section.module.scss +21 -19
  101. package/src/components/search/SearchDropdown/SearchDropdown.tsx +9 -7
  102. package/src/components/search/SearchHistory/SearchHistory.tsx +7 -2
  103. package/src/components/search/SearchInput/SearchInput.tsx +21 -8
  104. package/src/components/search/SearchProductItem/SearchProductItem.tsx +10 -3
  105. package/src/components/search/SearchTop/SearchTop.tsx +30 -24
  106. package/src/components/search/Sort/Sort.tsx +17 -19
  107. package/src/components/sections/Alert/Alert.tsx +6 -1
  108. package/src/components/sections/BannerNewsletter/section.module.scss +6 -4
  109. package/src/components/sections/BannerText/section.module.scss +5 -3
  110. package/src/components/sections/Breadcrumb/Breadcrumb.tsx +6 -2
  111. package/src/components/sections/Breadcrumb/section.module.scss +7 -5
  112. package/src/components/sections/EmptyState/section.module.scss +5 -3
  113. package/src/components/sections/Footer/Footer.tsx +1 -5
  114. package/src/components/sections/Footer/section.module.scss +10 -8
  115. package/src/components/sections/Hero/Hero.tsx +3 -1
  116. package/src/components/sections/Hero/section.module.scss +6 -4
  117. package/src/components/sections/Incentives/section.module.scss +5 -3
  118. package/src/components/sections/Navbar/Navbar.tsx +45 -0
  119. package/src/components/sections/Navbar/section.module.scss +34 -33
  120. package/src/components/sections/Newsletter/section.module.scss +10 -8
  121. package/src/components/sections/ProductDetails/ProductDetails.tsx +23 -1
  122. package/src/components/sections/ProductDetails/section.module.scss +32 -30
  123. package/src/components/sections/ProductGallery/EmptyGallery.tsx +13 -16
  124. package/src/components/sections/ProductGallery/section.module.scss +42 -39
  125. package/src/components/sections/ProductShelf/section.module.scss +22 -17
  126. package/src/components/sections/ProductTiles/section.module.scss +15 -13
  127. package/src/components/sections/RegionBar/section.module.scss +5 -3
  128. package/src/components/sections/ScrollToTopButton/ScrollToTopButton.tsx +4 -3
  129. package/src/components/sections/ScrollToTopButton/section.module.scss +4 -2
  130. package/src/components/templates/LandingPage/LandingPage.tsx +22 -16
  131. package/src/components/templates/ProductListingPage/ProductListing.tsx +1 -13
  132. package/src/components/templates/ProductListingPage/ProductListingPage.tsx +8 -3
  133. package/src/components/ui/Breadcrumb/Breadcrumb.tsx +14 -11
  134. package/src/components/ui/Button/ButtonSignIn/ButtonSignIn.tsx +2 -1
  135. package/src/components/ui/Button/ButtonSignIn/ButtonSignInFallback/ButtonSignInFallback.tsx +3 -1
  136. package/src/components/ui/Link/Link.tsx +19 -2
  137. package/src/components/ui/LinkButton/LinkButton.tsx +28 -0
  138. package/src/components/ui/LinkButton/index.ts +2 -0
  139. package/src/components/ui/LocalizationButton/LocalizationButton.tsx +124 -0
  140. package/src/components/ui/LocalizationButton/index.ts +1 -0
  141. package/src/components/ui/PickupPoints/PickupPointCards.tsx +2 -4
  142. package/src/components/ui/ProductComparison/ProductComparisonSidebar.tsx +34 -17
  143. package/src/components/ui/ProductDescription/ProductDescription.tsx +8 -3
  144. package/src/components/ui/ProductDetails/AddToCartLoadingSkeleton.tsx +6 -2
  145. package/src/components/ui/ProductDetails/ProductDetailsSettings.tsx +17 -5
  146. package/src/components/ui/ProductGallery/ProductGallery.tsx +7 -3
  147. package/src/components/ui/ProductGallery/ProductGalleryPage.tsx +1 -3
  148. package/src/components/ui/ShippingSimulation/ShippingSimulation.tsx +6 -1
  149. package/src/customizations/src/styles/custom-mixins.scss +0 -2
  150. package/src/experimental/index.ts +26 -0
  151. package/src/experimental/myAccountServerSideProps.ts +11 -2
  152. package/src/experimental/searchServerSideFunctions/getServerSideProps.ts +13 -7
  153. package/src/experimental/searchServerSideFunctions/getStaticProps.ts +5 -4
  154. package/src/instrumentation.ts +20 -6
  155. package/src/pages/404.tsx +5 -4
  156. package/src/pages/500.tsx +5 -4
  157. package/src/pages/[...slug].tsx +7 -4
  158. package/src/pages/[slug]/p.tsx +26 -8
  159. package/src/pages/_app.tsx +9 -1
  160. package/src/pages/api/fs/logout.ts +3 -2
  161. package/src/pages/api/graphql.ts +7 -23
  162. package/src/pages/api/preview.ts +21 -8
  163. package/src/pages/checkout.tsx +15 -5
  164. package/src/pages/index.tsx +18 -9
  165. package/src/pages/login.tsx +5 -4
  166. package/src/pages/pvt/account/403.tsx +11 -2
  167. package/src/pages/pvt/account/404.tsx +13 -3
  168. package/src/pages/pvt/account/index.tsx +6 -4
  169. package/src/pages/pvt/account/orders/[id].tsx +11 -3
  170. package/src/pages/pvt/account/orders/index.tsx +11 -3
  171. package/src/pages/pvt/account/profile.tsx +11 -2
  172. package/src/pages/pvt/account/security.tsx +11 -2
  173. package/src/pages/pvt/account/user-details.tsx +11 -2
  174. package/src/pages/s.tsx +26 -6
  175. package/src/proxy.ts +154 -0
  176. package/src/sdk/account/refreshToken.ts +4 -4
  177. package/src/sdk/account/useReorder.ts +8 -2
  178. package/src/sdk/analytics/platform/vtex/search.ts +3 -2
  179. package/src/sdk/cart/redirectToCheckout.ts +14 -8
  180. package/src/sdk/cart/useCheckoutButton.ts +7 -1
  181. package/src/sdk/deliveryPromise/useDeliveryPromise.ts +10 -18
  182. package/src/sdk/graphql/request.ts +102 -50
  183. package/src/sdk/localization/bindingSelector.ts +91 -0
  184. package/src/sdk/localization/index.ts +4 -0
  185. package/src/sdk/localization/match-url.ts +64 -0
  186. package/src/sdk/localization/types.ts +31 -0
  187. package/src/sdk/localization/useBindingSelector.ts +183 -0
  188. package/src/sdk/localization/useLocaleValidation.ts +49 -0
  189. package/src/sdk/localization/useLocalizationConfig.tsx +160 -0
  190. package/src/sdk/offer/fetcher.ts +3 -2
  191. package/src/sdk/product/useLocalizedVariables.ts +1 -1
  192. package/src/sdk/product/usePageProductsQuery.ts +2 -2
  193. package/src/sdk/product/useProductGalleryQuery.ts +1 -2
  194. package/src/sdk/product/useProductLink.ts +3 -1
  195. package/src/sdk/search/formatSearchPath.ts +28 -3
  196. package/src/sdk/search/state.ts +22 -13
  197. package/src/sdk/search/useSearchBase.ts +10 -0
  198. package/src/sdk/search/useSearchHistory.ts +41 -7
  199. package/src/sdk/session/index.ts +21 -3
  200. package/src/sdk/shipping/useShippingSimulation.ts +10 -2
  201. package/src/sdk/tsconfig.json +6 -0
  202. package/src/sdk/ui/useLink.ts +48 -0
  203. package/src/server/cms/global.ts +40 -0
  204. package/src/server/cms/index.ts +18 -10
  205. package/src/server/cms/pdp.ts +1 -0
  206. package/src/server/cms/plp.ts +3 -0
  207. package/src/server/content/service.ts +36 -24
  208. package/src/server/content/types.ts +10 -3
  209. package/src/server/index.ts +27 -20
  210. package/src/server/options.ts +27 -2
  211. package/src/styles/global/index.scss +10 -7
  212. package/src/styles/main.scss +3 -3
  213. package/src/typings/locales.ts +41 -0
  214. package/src/utils/fetchProductGallerySSR.ts +3 -1
  215. package/src/utils/getBaseDomain.ts +2 -1
  216. package/src/utils/getRequestHostname.ts +26 -0
  217. package/src/utils/globalSettings.ts +11 -0
  218. package/src/utils/localization/bindingPaths.ts +337 -0
  219. package/src/utils/localization/validateLocaleForHostname.ts +69 -0
  220. package/src/utils/localization/withLocaleValidation.ts +36 -0
  221. package/src/utils/utilities.ts +22 -0
  222. package/test/pages/api/preview.test.ts +93 -0
  223. package/test/sdk/localization/bindingSelector.test.ts +246 -0
  224. package/test/sdk/localization/store-url.browser.test.ts +140 -0
  225. package/test/sdk/localization/store-url.test.ts +96 -0
  226. package/test/sdk/localization/useBindingSelector.test.tsx +219 -0
  227. package/test/sdk/search/useSearchHistory.test.ts +222 -0
  228. package/test/server/cms/index.test.ts +3 -4
  229. package/test/server/content/service.test.ts +98 -0
  230. package/test/server/index.test.ts +10 -22
  231. package/test/utils/cookieCacheBusting.test.ts +32 -24
  232. package/test/utils/getRequestHostname.test.ts +71 -0
  233. package/test/utils/localization/bindingPaths.test.ts +706 -0
  234. package/test/utils/match-url.test.ts +388 -0
  235. package/tsconfig.json +11 -3
  236. package/vitest.config.ts +61 -0
  237. package/.next/BUILD_ID +0 -1
  238. package/.next/build-manifest.json +0 -197
  239. package/.next/cache/.tsbuildinfo +0 -1
  240. package/.next/cache/config.json +0 -7
  241. package/.next/cache/webpack/client-production/0.pack +0 -0
  242. package/.next/cache/webpack/client-production/index.pack +0 -0
  243. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  244. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  245. package/.next/cache/webpack/server-production/0.pack +0 -0
  246. package/.next/cache/webpack/server-production/index.pack +0 -0
  247. package/.next/export-marker.json +0 -1
  248. package/.next/images-manifest.json +0 -1
  249. package/.next/next-minimal-server.js.nft.json +0 -1
  250. package/.next/next-server.js.nft.json +0 -1
  251. package/.next/package.json +0 -1
  252. package/.next/prerender-manifest.js +0 -1
  253. package/.next/prerender-manifest.json +0 -1
  254. package/.next/react-loadable-manifest.json +0 -478
  255. package/.next/required-server-files.json +0 -1
  256. package/.next/routes-manifest.json +0 -1
  257. package/.next/server/chunks/1280.js +0 -1
  258. package/.next/server/chunks/1454.js +0 -1
  259. package/.next/server/chunks/1554.js +0 -1
  260. package/.next/server/chunks/1607.js +0 -1
  261. package/.next/server/chunks/1780.js +0 -1
  262. package/.next/server/chunks/1917.js +0 -1
  263. package/.next/server/chunks/1972.js +0 -1
  264. package/.next/server/chunks/2230.js +0 -1
  265. package/.next/server/chunks/2249.js +0 -1
  266. package/.next/server/chunks/2430.js +0 -1
  267. package/.next/server/chunks/2445.js +0 -12
  268. package/.next/server/chunks/2570.js +0 -1
  269. package/.next/server/chunks/2792.js +0 -1
  270. package/.next/server/chunks/2903.js +0 -1
  271. package/.next/server/chunks/294.js +0 -1
  272. package/.next/server/chunks/2955.js +0 -1
  273. package/.next/server/chunks/3006.js +0 -1
  274. package/.next/server/chunks/3029.js +0 -1
  275. package/.next/server/chunks/3060.js +0 -1
  276. package/.next/server/chunks/3408.js +0 -1
  277. package/.next/server/chunks/3483.js +0 -1
  278. package/.next/server/chunks/3683.js +0 -1
  279. package/.next/server/chunks/3836.js +0 -1
  280. package/.next/server/chunks/3890.js +0 -494
  281. package/.next/server/chunks/3922.js +0 -1
  282. package/.next/server/chunks/3945.js +0 -1
  283. package/.next/server/chunks/3951.js +0 -7
  284. package/.next/server/chunks/416.js +0 -1
  285. package/.next/server/chunks/4194.js +0 -1
  286. package/.next/server/chunks/4365.js +0 -1
  287. package/.next/server/chunks/4451.js +0 -1
  288. package/.next/server/chunks/4803.js +0 -1
  289. package/.next/server/chunks/4913.js +0 -13
  290. package/.next/server/chunks/5402.js +0 -1
  291. package/.next/server/chunks/5723.js +0 -13
  292. package/.next/server/chunks/5796.js +0 -1
  293. package/.next/server/chunks/6393.js +0 -1
  294. package/.next/server/chunks/6457.js +0 -6
  295. package/.next/server/chunks/6698.js +0 -1
  296. package/.next/server/chunks/6804.js +0 -6
  297. package/.next/server/chunks/6886.js +0 -1
  298. package/.next/server/chunks/7098.js +0 -9
  299. package/.next/server/chunks/7169.js +0 -1
  300. package/.next/server/chunks/7228.js +0 -1
  301. package/.next/server/chunks/7275.js +0 -1
  302. package/.next/server/chunks/7371.js +0 -1
  303. package/.next/server/chunks/7692.js +0 -1
  304. package/.next/server/chunks/7799.js +0 -1
  305. package/.next/server/chunks/8068.js +0 -1
  306. package/.next/server/chunks/83.js +0 -1
  307. package/.next/server/chunks/831.js +0 -1
  308. package/.next/server/chunks/8563.js +0 -1
  309. package/.next/server/chunks/8569.js +0 -1
  310. package/.next/server/chunks/8687.js +0 -1
  311. package/.next/server/chunks/870.js +0 -1
  312. package/.next/server/chunks/8737.js +0 -1
  313. package/.next/server/chunks/8741.js +0 -1
  314. package/.next/server/chunks/9088.js +0 -1
  315. package/.next/server/chunks/9117.js +0 -1
  316. package/.next/server/chunks/9237.js +0 -1
  317. package/.next/server/chunks/948.js +0 -3
  318. package/.next/server/chunks/9563.js +0 -3
  319. package/.next/server/chunks/9570.js +0 -1
  320. package/.next/server/chunks/9740.js +0 -1
  321. package/.next/server/chunks/9853.js +0 -1
  322. package/.next/server/chunks/9984.js +0 -1
  323. package/.next/server/chunks/9985.js +0 -1
  324. package/.next/server/chunks/9990.js +0 -1
  325. package/.next/server/chunks/ButtonSignIn.js +0 -1
  326. package/.next/server/chunks/Dropdown.js +0 -1
  327. package/.next/server/chunks/DropdownButton.js +0 -1
  328. package/.next/server/chunks/DropdownItem.js +0 -1
  329. package/.next/server/chunks/DropdownMenu.js +0 -1
  330. package/.next/server/chunks/FilterSkeleton.js +0 -1
  331. package/.next/server/chunks/ScrollToTopButton.js +0 -1
  332. package/.next/server/chunks/UIBannerText.js +0 -1
  333. package/.next/server/chunks/UISKUMatrixSidebar.js +0 -1
  334. package/.next/server/chunks/font-manifest.json +0 -1
  335. package/.next/server/edge-instrumentation.js +0 -2
  336. package/.next/server/edge-instrumentation.js.map +0 -1
  337. package/.next/server/edge-runtime-webpack.js +0 -157
  338. package/.next/server/edge-runtime-webpack.js.map +0 -1
  339. package/.next/server/font-manifest.json +0 -1
  340. package/.next/server/functions-config-manifest.json +0 -1
  341. package/.next/server/instrumentation.js +0 -1
  342. package/.next/server/instrumentation.js.nft.json +0 -1
  343. package/.next/server/middleware-build-manifest.js +0 -1
  344. package/.next/server/middleware-manifest.json +0 -6
  345. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  346. package/.next/server/next-font-manifest.js +0 -1
  347. package/.next/server/next-font-manifest.json +0 -1
  348. package/.next/server/pages/404.js +0 -1
  349. package/.next/server/pages/404.js.nft.json +0 -1
  350. package/.next/server/pages/500.js +0 -1
  351. package/.next/server/pages/500.js.nft.json +0 -1
  352. package/.next/server/pages/[...slug].js +0 -1
  353. package/.next/server/pages/[...slug].js.nft.json +0 -1
  354. package/.next/server/pages/[slug]/p.js +0 -1
  355. package/.next/server/pages/[slug]/p.js.nft.json +0 -1
  356. package/.next/server/pages/_app.js +0 -1
  357. package/.next/server/pages/_app.js.nft.json +0 -1
  358. package/.next/server/pages/_document.js +0 -1
  359. package/.next/server/pages/_document.js.nft.json +0 -1
  360. package/.next/server/pages/_error.js +0 -1
  361. package/.next/server/pages/_error.js.nft.json +0 -1
  362. package/.next/server/pages/api/fs/logout.js +0 -1
  363. package/.next/server/pages/api/fs/logout.js.nft.json +0 -1
  364. package/.next/server/pages/api/graphql.js +0 -3
  365. package/.next/server/pages/api/graphql.js.nft.json +0 -1
  366. package/.next/server/pages/api/health/live.js +0 -1
  367. package/.next/server/pages/api/health/live.js.nft.json +0 -1
  368. package/.next/server/pages/api/health/ready.js +0 -1
  369. package/.next/server/pages/api/health/ready.js.nft.json +0 -1
  370. package/.next/server/pages/api/preview.js +0 -1
  371. package/.next/server/pages/api/preview.js.nft.json +0 -1
  372. package/.next/server/pages/checkout.js +0 -1
  373. package/.next/server/pages/checkout.js.nft.json +0 -1
  374. package/.next/server/pages/en-US/404.html +0 -42
  375. package/.next/server/pages/en-US/404.json +0 -1
  376. package/.next/server/pages/en-US/500.html +0 -42
  377. package/.next/server/pages/en-US/500.json +0 -1
  378. package/.next/server/pages/en-US/checkout.html +0 -42
  379. package/.next/server/pages/en-US/checkout.json +0 -1
  380. package/.next/server/pages/en-US/login.html +0 -42
  381. package/.next/server/pages/en-US/login.json +0 -1
  382. package/.next/server/pages/en-US/s.html +0 -42
  383. package/.next/server/pages/en-US/s.json +0 -1
  384. package/.next/server/pages/en-US.html +0 -42
  385. package/.next/server/pages/en-US.json +0 -1
  386. package/.next/server/pages/index.js +0 -1
  387. package/.next/server/pages/index.js.nft.json +0 -1
  388. package/.next/server/pages/login.js +0 -1
  389. package/.next/server/pages/login.js.nft.json +0 -1
  390. package/.next/server/pages/pvt/account/403.js +0 -1
  391. package/.next/server/pages/pvt/account/403.js.nft.json +0 -1
  392. package/.next/server/pages/pvt/account/404.js +0 -1
  393. package/.next/server/pages/pvt/account/404.js.nft.json +0 -1
  394. package/.next/server/pages/pvt/account/[...unknown].js +0 -1
  395. package/.next/server/pages/pvt/account/[...unknown].js.nft.json +0 -1
  396. package/.next/server/pages/pvt/account/orders/[id].js +0 -1
  397. package/.next/server/pages/pvt/account/orders/[id].js.nft.json +0 -1
  398. package/.next/server/pages/pvt/account/orders.js +0 -1
  399. package/.next/server/pages/pvt/account/orders.js.nft.json +0 -1
  400. package/.next/server/pages/pvt/account/profile.js +0 -1
  401. package/.next/server/pages/pvt/account/profile.js.nft.json +0 -1
  402. package/.next/server/pages/pvt/account/security.js +0 -1
  403. package/.next/server/pages/pvt/account/security.js.nft.json +0 -1
  404. package/.next/server/pages/pvt/account/user-details.js +0 -1
  405. package/.next/server/pages/pvt/account/user-details.js.nft.json +0 -1
  406. package/.next/server/pages/pvt/account.js +0 -1
  407. package/.next/server/pages/pvt/account.js.nft.json +0 -1
  408. package/.next/server/pages/s.js +0 -1
  409. package/.next/server/pages/s.js.nft.json +0 -1
  410. package/.next/server/pages-manifest.json +0 -1
  411. package/.next/server/webpack-api-runtime.js +0 -1
  412. package/.next/server/webpack-runtime.js +0 -1
  413. package/.next/static/chunks/227-f109b24190a008ab.js +0 -8
  414. package/.next/static/chunks/2284.185d834d9829b652.js +0 -1
  415. package/.next/static/chunks/2851.e68ed3c8d27a032a.js +0 -1
  416. package/.next/static/chunks/2927.23bae2c79f0ac0f3.js +0 -1
  417. package/.next/static/chunks/3155.7bc4c730a79d9ecb.js +0 -1
  418. package/.next/static/chunks/3166-0b30a3887c0c346d.js +0 -1
  419. package/.next/static/chunks/3399.017c5209b74b0d97.js +0 -1
  420. package/.next/static/chunks/3483.ef53d632a763da3f.js +0 -1
  421. package/.next/static/chunks/349.b3b38e1e9f719dda.js +0 -1
  422. package/.next/static/chunks/3802.5e8b0b689eacc0f8.js +0 -1
  423. package/.next/static/chunks/3836.620480018be48233.js +0 -1
  424. package/.next/static/chunks/4436.e7af66f0b654ee36.js +0 -1
  425. package/.next/static/chunks/4803.b1920b6e3a1a6304.js +0 -1
  426. package/.next/static/chunks/5796.4351370494d8b8b6.js +0 -1
  427. package/.next/static/chunks/6393.55f991b1a6bb4fe7.js +0 -1
  428. package/.next/static/chunks/6700.b23221a57514e737.js +0 -1
  429. package/.next/static/chunks/6789.960162355435a81d.js +0 -1
  430. package/.next/static/chunks/7191-befad64ba238a817.js +0 -1
  431. package/.next/static/chunks/7692.8d5bf4560341a2f6.js +0 -1
  432. package/.next/static/chunks/7861.7f9f1a124a43da30.js +0 -6
  433. package/.next/static/chunks/8068.43663fb64762f7b8.js +0 -1
  434. package/.next/static/chunks/83.e0c16f0299b364a5.js +0 -1
  435. package/.next/static/chunks/8325.dabe9aa22eaadeed.js +0 -1
  436. package/.next/static/chunks/8587.53c8ce185ed1a2cb.js +0 -1
  437. package/.next/static/chunks/9173-e89da04079c35360.js +0 -2
  438. package/.next/static/chunks/9237.7555603703f81bf7.js +0 -1
  439. package/.next/static/chunks/9298-1d1ed0a54133cb59.js +0 -28
  440. package/.next/static/chunks/9399.d116a7fd62024783.js +0 -1
  441. package/.next/static/chunks/941.3e2782ab9c490eb0.js +0 -1
  442. package/.next/static/chunks/9701.f9a0bfffba8807dc.js +0 -1
  443. package/.next/static/chunks/9909.787576b171184aa5.js +0 -1
  444. package/.next/static/chunks/9960.7ef77f8a8b046170.js +0 -1
  445. package/.next/static/chunks/9979.aedbc094bdc2c599.js +0 -1
  446. package/.next/static/chunks/BannerNewsletter.00328ad162109908.js +0 -1
  447. package/.next/static/chunks/BannerText.dbbec87cadb8a521.js +0 -1
  448. package/.next/static/chunks/ButtonSignIn.f6e210eaca873e48.js +0 -1
  449. package/.next/static/chunks/CartItem.b34e295377f6f94f.js +0 -1
  450. package/.next/static/chunks/CartSidebar.ac447d1ef6276da1.js +0 -1
  451. package/.next/static/chunks/Dropdown.38b48c749bad6b60.js +0 -1
  452. package/.next/static/chunks/DropdownButton.66fa6b25dddb3a07.js +0 -1
  453. package/.next/static/chunks/DropdownItem.38b8f5a07c7f422a.js +0 -1
  454. package/.next/static/chunks/DropdownMenu.48b11521a24c6efd.js +0 -1
  455. package/.next/static/chunks/EmptyCart.320e2f94a0d5e6b1.js +0 -1
  456. package/.next/static/chunks/FilterSkeleton.7ab99e28f92341c9.js +0 -1
  457. package/.next/static/chunks/Footer.166b02c2f13980c6.js +0 -1
  458. package/.next/static/chunks/Gift.c49ba26da2fbab5e.js +0 -1
  459. package/.next/static/chunks/Newsletter.fc406f6029057022.js +0 -1
  460. package/.next/static/chunks/OrderSummary.5957d69f990d9add.js +0 -1
  461. package/.next/static/chunks/PreviewTag.f4f0c8710a7bcad9.js +0 -1
  462. package/.next/static/chunks/ProductShelf.cc46f5cdeeaeaff6.js +0 -1
  463. package/.next/static/chunks/ProductTiles.9b804e51b0704d60.js +0 -1
  464. package/.next/static/chunks/RegionModal.319ad44250cb12d2.js +0 -1
  465. package/.next/static/chunks/RegionSlider.0e0e93369f4f9c92.js +0 -1
  466. package/.next/static/chunks/ScrollToTopButton.c15431f2e8bb93ef.js +0 -1
  467. package/.next/static/chunks/ShoppingAssistant.ba191eb4dbed67e5.js +0 -1
  468. package/.next/static/chunks/Toast.5f90f0436708be5e.js +0 -1
  469. package/.next/static/chunks/UIBannerText.7315b16af4457059.js +0 -1
  470. package/.next/static/chunks/UISKUMatrixSidebar.b4349b2682bbe183.js +0 -1
  471. package/.next/static/chunks/UIToast.de15325248043ce5.js +0 -1
  472. package/.next/static/chunks/framework-d514426edf885c68.js +0 -33
  473. package/.next/static/chunks/main-ec03882c4375091d.js +0 -1
  474. package/.next/static/chunks/pages/404-e3dfbbac003b02a2.js +0 -1
  475. package/.next/static/chunks/pages/500-c7814e085081d7b8.js +0 -1
  476. package/.next/static/chunks/pages/[...slug]-dc8a395a43b081f1.js +0 -1
  477. package/.next/static/chunks/pages/[slug]/p-644f1132f5a0f736.js +0 -1
  478. package/.next/static/chunks/pages/_app-84aaff8a9d4de60e.js +0 -1
  479. package/.next/static/chunks/pages/_error-2b0148be56a716e9.js +0 -1
  480. package/.next/static/chunks/pages/checkout-2071467ad42dfb99.js +0 -1
  481. package/.next/static/chunks/pages/index-8774d5b4a8744eb2.js +0 -1
  482. package/.next/static/chunks/pages/login-e74747c9f9cb5b49.js +0 -1
  483. package/.next/static/chunks/pages/pvt/account/403-491e6b062487b30f.js +0 -1
  484. package/.next/static/chunks/pages/pvt/account/404-5ad472d9f2ee1980.js +0 -1
  485. package/.next/static/chunks/pages/pvt/account/[...unknown]-f80f645594d2740c.js +0 -1
  486. package/.next/static/chunks/pages/pvt/account/orders/[id]-64e42157c0974c48.js +0 -1
  487. package/.next/static/chunks/pages/pvt/account/orders-faab39f2aff05fae.js +0 -1
  488. package/.next/static/chunks/pages/pvt/account/profile-9672177ee2665bc0.js +0 -1
  489. package/.next/static/chunks/pages/pvt/account/security-03eb1ccab9a30563.js +0 -1
  490. package/.next/static/chunks/pages/pvt/account/user-details-7838e3f79781596c.js +0 -1
  491. package/.next/static/chunks/pages/pvt/account-65fefcc699344bdb.js +0 -1
  492. package/.next/static/chunks/pages/s-162ba789e6611175.js +0 -1
  493. package/.next/static/chunks/polyfills-c67a75d1b6f99dc8.js +0 -1
  494. package/.next/static/chunks/webpack-dbc0d9f67d2f928f.js +0 -1
  495. package/.next/static/css/02259c549b2179f2.css +0 -1
  496. package/.next/static/css/02eaf202d3d11fd1.css +0 -1
  497. package/.next/static/css/033e241c58ba6fbb.css +0 -1
  498. package/.next/static/css/042d012bc1895b5c.css +0 -1
  499. package/.next/static/css/14176a4704ff97b2.css +0 -1
  500. package/.next/static/css/146a8678babc61bf.css +0 -1
  501. package/.next/static/css/16d65422bfa80f51.css +0 -1
  502. package/.next/static/css/1c4983f11b861ea0.css +0 -1
  503. package/.next/static/css/204754bbd8cc4bef.css +0 -1
  504. package/.next/static/css/24d91007fc96be10.css +0 -1
  505. package/.next/static/css/2980acad3f8e1028.css +0 -1
  506. package/.next/static/css/2c19433e38fd7533.css +0 -1
  507. package/.next/static/css/31380ebc6e671486.css +0 -1
  508. package/.next/static/css/42df884711219edb.css +0 -1
  509. package/.next/static/css/4f0597b0bf0ef2e1.css +0 -1
  510. package/.next/static/css/54cedf4b65e5863f.css +0 -1
  511. package/.next/static/css/6580147d7ab8fcca.css +0 -1
  512. package/.next/static/css/6819dddf2b1b5ea7.css +0 -1
  513. package/.next/static/css/7ef7762f412ed665.css +0 -1
  514. package/.next/static/css/82f3cd529b672812.css +0 -1
  515. package/.next/static/css/837662922091162f.css +0 -1
  516. package/.next/static/css/8e6ab59ace21e03b.css +0 -1
  517. package/.next/static/css/a852afa9be31e946.css +0 -1
  518. package/.next/static/css/b684b347c5cc6514.css +0 -1
  519. package/.next/static/css/bcdaef0a83277ef5.css +0 -1
  520. package/.next/static/css/c33615999008d3f9.css +0 -1
  521. package/.next/static/css/c34f6ea9953e2f63.css +0 -1
  522. package/.next/static/css/ea11d74a2848b093.css +0 -1
  523. package/.next/static/css/f16438bcf4508fb3.css +0 -1
  524. package/.next/static/css/f60366555f563deb.css +0 -1
  525. package/.next/static/es3Z4hhE6B4Nut0ZqqUuB/_buildManifest.js +0 -1
  526. package/.next/static/es3Z4hhE6B4Nut0ZqqUuB/_ssgManifest.js +0 -1
  527. package/.next/trace +0 -143
  528. package/.turbo/turbo-build.log +0 -134
  529. package/jest.config.js +0 -17
  530. package/public/~partytown/debug/partytown-atomics.js +0 -556
  531. package/public/~partytown/debug/partytown-media.js +0 -374
  532. package/public/~partytown/debug/partytown-sandbox-sw.js +0 -543
  533. package/public/~partytown/debug/partytown-sw.js +0 -59
  534. package/public/~partytown/debug/partytown-ww-atomics.js +0 -1789
  535. package/public/~partytown/debug/partytown-ww-sw.js +0 -1781
  536. package/public/~partytown/debug/partytown.js +0 -72
  537. package/public/~partytown/partytown-atomics.js +0 -2
  538. package/public/~partytown/partytown-media.js +0 -2
  539. package/public/~partytown/partytown-sw.js +0 -2
  540. package/public/~partytown/partytown.js +0 -2
  541. package/src/middleware__DISABLED.ts +0 -65
  542. package/src/server/generator/generateGraphQLSchemaFile.ts +0 -3
  543. package/src/server/generator/schema.ts +0 -81
@@ -0,0 +1,160 @@
1
+ import config from 'discovery.config'
2
+ import deepEqual from 'fast-deep-equal'
3
+ import React, { useEffect, useRef, useState } from 'react'
4
+ import { sessionStore } from '../session'
5
+ import { matchURLBinding } from './match-url'
6
+
7
+ type Settings = {
8
+ locale: string
9
+ currency: { code: string; symbol: string }
10
+ salesChannel: string
11
+ storeURL: string
12
+ }
13
+
14
+ export const useLocalizationConfig = (params?: { url?: string | URL }) => {
15
+ const defaultConfig = config.localization.locales[
16
+ config.localization.defaultLocale
17
+ ] as ConfigType
18
+ const defaultBinding =
19
+ defaultConfig.bindings.find((el) => el.isDefault) ??
20
+ defaultConfig.bindings.at(0)
21
+
22
+ if (!defaultBinding)
23
+ throw new Error(
24
+ 'Localization configuration invalid: not found default binding'
25
+ )
26
+
27
+ const [settings, setSettings] = useState<Settings>(getSettings(params))
28
+
29
+ const newSettings = getSettings(params)
30
+ if (deepEqual(settings, newSettings) === false) {
31
+ return setSettings(newSettings)
32
+ }
33
+
34
+ // Use a ref to always hold the latest session without causing re-renders or
35
+ // re-running the sync effect. The sync effect only needs to react to `settings`
36
+ // changes, not to every session update triggered by the optimistic middleware.
37
+ const sessionRef = useRef(sessionStore.read() ?? sessionStore.readInitial())
38
+
39
+ useEffect(() => {
40
+ return sessionStore.subscribe((newSession) => {
41
+ sessionRef.current = newSession
42
+ })
43
+ }, [])
44
+
45
+ useEffect(() => {
46
+ if (!settings) return
47
+
48
+ const session = sessionRef.current
49
+ const channel = JSON.parse(session.channel ?? '{}') ?? {}
50
+ channel.salesChannel = settings.salesChannel
51
+
52
+ const newSession = {
53
+ ...session,
54
+ locale: settings.locale,
55
+ currency: settings.currency,
56
+ channel: JSON.stringify(channel),
57
+ }
58
+
59
+ if (
60
+ newSession.channel !== session.channel ||
61
+ newSession.locale !== session.locale ||
62
+ deepEqual(newSession.currency, session.currency) === false
63
+ ) {
64
+ sessionStore.set(newSession)
65
+ }
66
+ }, [settings])
67
+
68
+ return settings
69
+ }
70
+
71
+ type ConfigType =
72
+ (typeof config)['localization']['locales'][keyof (typeof config)['localization']['locales']]
73
+
74
+ function getSettingsFromConfig(
75
+ configObject: ConfigType,
76
+ binding: ConfigType['bindings'][number]
77
+ ): Settings {
78
+ const salesChannel = Number(binding.salesChannel)
79
+
80
+ return {
81
+ currency: {
82
+ code: binding.currencyCode,
83
+ symbol: config.localization.currencies[binding.currencyCode].symbol,
84
+ },
85
+ locale: configObject.code,
86
+ salesChannel: `${isNaN(salesChannel) ? 1 : salesChannel}`,
87
+ storeURL: binding.url,
88
+ }
89
+ }
90
+
91
+ export function getSettings(params?: { url?: string | URL }) {
92
+ let url = params?.url ?? ''
93
+ const defaultConfig = config.localization.locales[
94
+ config.localization.defaultLocale
95
+ ] as ConfigType
96
+
97
+ const defaultBinding =
98
+ defaultConfig.bindings.find((el) => el.isDefault) ??
99
+ defaultConfig.bindings.at(0)
100
+
101
+ if (!defaultBinding)
102
+ throw new Error(
103
+ 'Localization configuration invalid: not found default binding'
104
+ )
105
+
106
+ const defaultSettings = getSettingsFromConfig(defaultConfig, defaultBinding)
107
+
108
+ if (!url) {
109
+ if (typeof window === 'undefined') {
110
+ return defaultSettings
111
+ }
112
+
113
+ url = window.location.href
114
+ }
115
+
116
+ if (url instanceof URL) url = url.toString()
117
+
118
+ if (!config.localization) {
119
+ const Err = new Error(
120
+ 'Missing localization configuration in faststore config file.'
121
+ )
122
+ console.error(Err)
123
+ throw Err
124
+ }
125
+
126
+ const { config: regionConfig, binding } = matchURLBinding(url)
127
+ if (!!regionConfig && !!binding) {
128
+ return getSettingsFromConfig(regionConfig, binding)
129
+ }
130
+
131
+ return defaultSettings
132
+ }
133
+
134
+ export const getStoreURL = () => {
135
+ // If localization is not enabled, use storeUrl from config
136
+ if (!config.localization?.enabled === true) {
137
+ return config.storeUrl
138
+ }
139
+
140
+ return getSettings().storeURL
141
+ }
142
+
143
+ /** @description receives an react component and returns a new component with the storeURL as optional */
144
+ export function withStoreURL<
145
+ Props extends { storeURL: string },
146
+ PartialProps extends Omit<Props, 'storeURL'> & { storeURL?: string },
147
+ >(Component: React.ComponentType<Props>): React.ComponentType<PartialProps> {
148
+ return (props: PartialProps) => {
149
+ return React.createElement(Component, {
150
+ ...props,
151
+ storeURL: props.storeURL ?? getStoreURL(),
152
+ } as unknown as Props)
153
+ }
154
+ }
155
+
156
+ export default {
157
+ withStoreURL,
158
+ getStoreURL,
159
+ useLocalizationConfig,
160
+ }
@@ -1,11 +1,12 @@
1
1
  import type { ProductSearchResult } from '@faststore/api'
2
- import { api, storeUrl } from '../../../discovery.config'
2
+ import { api } from '../../../discovery.config'
3
+ import { getStoreURL } from '../localization/useLocalizationConfig'
3
4
 
4
5
  const IS_PROD = process.env.NODE_ENV === 'production'
5
6
 
6
7
  export function getUrl(skuId: string) {
7
8
  const base = IS_PROD
8
- ? storeUrl
9
+ ? new URL(getStoreURL()).origin
9
10
  : `https://${api.storeId}.${api.environment}.com.br`
10
11
  const url = new URL(`${base}/api/intelligent-search/product_search`)
11
12
  url.searchParams.append('query', `sku.id:${skuId}`)
@@ -19,7 +19,7 @@ export const useLocalizedVariables = ({
19
19
  return useMemo(() => {
20
20
  return {
21
21
  first: first ?? ITEMS_PER_SECTION,
22
- after: after ?? '0',
22
+ after: String(after ?? 0),
23
23
  sort: sort ?? ('score_desc' as const),
24
24
  term: term ?? '',
25
25
  selectedFacets: [
@@ -1,10 +1,10 @@
1
- import storeConfig from 'discovery.config'
2
1
  import { useSearch } from '@faststore/sdk'
3
2
  import { gql } from '@generated'
4
3
  import type {
5
4
  ClientManyProductsQueryWithSearchIdQuery,
6
5
  ClientManyProductsQueryWithSearchIdQueryVariables,
7
6
  } from '@generated/graphql'
7
+ import storeConfig from 'discovery.config'
8
8
  import deepEquals from 'fast-deep-equal'
9
9
  import {
10
10
  createContext,
@@ -150,7 +150,7 @@ export const useCreateUseGalleryPage = (
150
150
  const { data } = useQuery<
151
151
  ClientManyProductsQueryWithSearchIdQuery,
152
152
  ClientManyProductsQueryWithSearchIdQueryVariables
153
- >(query, localizedVariables, {
153
+ >(query, localizedVariablesWithRegion, {
154
154
  fallbackData: null,
155
155
  suspense: true,
156
156
  doNotRun:
@@ -4,8 +4,7 @@ import { useQuery } from 'src/sdk/graphql/useQuery'
4
4
  import { useSession } from 'src/sdk/session'
5
5
  import { useLocalizedVariables } from './useLocalizedVariables'
6
6
 
7
- import { type SearchState, useSearch } from '@faststore/sdk'
8
- import type { Facet } from '@faststore/sdk/dist/types'
7
+ import { type Facet, type SearchState, useSearch } from '@faststore/sdk'
9
8
  import type {
10
9
  ClientManyProductsQueryQueryVariables,
11
10
  ClientProductGalleryQueryQuery as Query,
@@ -3,6 +3,7 @@ import type { ProductSummary_ProductFragment } from '@generated/graphql'
3
3
  import { useCallback } from 'react'
4
4
  import type { AnalyticsItem, SearchSelectItemEvent } from '../analytics/types'
5
5
  import { useSession } from '../session'
6
+ import { useLink } from '../ui/useLink'
6
7
 
7
8
  export type ProductLinkOptions = {
8
9
  index: number
@@ -15,6 +16,7 @@ export const useProductLink = ({
15
16
  product,
16
17
  selectedOffer,
17
18
  }: ProductLinkOptions) => {
19
+ const { resolveLink } = useLink()
18
20
  const { slug } = product
19
21
  const {
20
22
  currency: { code },
@@ -61,7 +63,7 @@ export const useProductLink = ({
61
63
  }, [code, product, index, selectedOffer])
62
64
 
63
65
  return {
64
- href: `/${slug}/p`,
66
+ href: resolveLink(`/${slug}/p`) ?? `/${slug}/p`,
65
67
  onClick,
66
68
  'data-testid': 'product-link',
67
69
  }
@@ -1,19 +1,44 @@
1
1
  import type { SearchState } from '@faststore/sdk'
2
2
  import { formatSearchState, initSearchState } from '@faststore/sdk'
3
+ import { useCallback } from 'react'
3
4
 
4
- type FormatSearchPath = {
5
+ import { useSearchBase } from 'src/sdk/search/useSearchBase'
6
+
7
+ const DEFAULT_SEARCH_BASE = '/s'
8
+
9
+ export type FormatSearchPathParams = {
5
10
  term: string
6
11
  sort?: SearchState['sort']
7
12
  }
8
13
 
9
- export const formatSearchPath = ({ term, sort }: FormatSearchPath) => {
14
+ /**
15
+ * Builds the search URL path for a given term and sort.
16
+ * Pass `base` (e.g. from resolveLink('/s')) to include locale/custom path so the path is correct for the current context.
17
+ */
18
+ export const formatSearchPath = (
19
+ { term, sort }: FormatSearchPathParams,
20
+ base: string = DEFAULT_SEARCH_BASE
21
+ ) => {
10
22
  const { pathname, search } = formatSearchState(
11
23
  initSearchState({
12
24
  term,
13
25
  sort,
14
- base: '/s',
26
+ base,
15
27
  })
16
28
  )
17
29
 
18
30
  return `${pathname}${search}`
19
31
  }
32
+
33
+ /**
34
+ * Hook that returns a function to build the search path with the current locale/custom path base.
35
+ */
36
+ export function useFormatSearchPath(): (
37
+ params: FormatSearchPathParams
38
+ ) => string {
39
+ const searchBase = useSearchBase()
40
+ return useCallback(
41
+ (params: FormatSearchPathParams) => formatSearchPath(params, searchBase),
42
+ [searchBase]
43
+ )
44
+ }
@@ -1,18 +1,27 @@
1
1
  import { useCallback } from 'react'
2
2
 
3
+ import { useLink } from 'src/sdk/ui/useLink'
4
+
3
5
  export const useApplySearchState = () => {
4
- return useCallback((url: URL) => {
5
- const newUrl = `${url.pathname}${url.search}`
6
+ const { resolveLink } = useLink()
7
+
8
+ return useCallback(
9
+ (url: URL) => {
10
+ const newUrl = `${url.pathname}${url.search}`
11
+ // Resolve so locale/custom path is preserved (global state may have base '/s' from an earlier route)
12
+ const resolved = resolveLink(newUrl) ?? newUrl
6
13
 
7
- // saves state on URL without triggering a re-render.
8
- window.history.replaceState(
9
- {
10
- ...window.history.state,
11
- as: newUrl,
12
- url: newUrl,
13
- },
14
- '',
15
- newUrl
16
- )
17
- }, [])
14
+ // saves state on URL without triggering a re-render.
15
+ window.history.replaceState(
16
+ {
17
+ ...window.history.state,
18
+ as: resolved,
19
+ url: resolved,
20
+ },
21
+ '',
22
+ resolved
23
+ )
24
+ },
25
+ [resolveLink]
26
+ )
18
27
  }
@@ -0,0 +1,10 @@
1
+ import { useLink } from 'src/sdk/ui/useLink'
2
+
3
+ /**
4
+ * Returns the resolved search base path (e.g. `/s`, `/emea-eur/s`, or `/pt-BR/s`)
5
+ * for building search URLs. Use with formatSearchPath so links respect locale and custom path.
6
+ */
7
+ export function useSearchBase(): string {
8
+ const { resolveLink } = useLink()
9
+ return resolveLink('/s') ?? '/s'
10
+ }
@@ -1,35 +1,69 @@
1
1
  import { createStore } from '@faststore/sdk'
2
-
2
+ import { useEffect, useMemo } from 'react'
3
+ import config from 'discovery.config'
3
4
  import { useStore } from '../useStore'
5
+ import { useSession } from '../session'
6
+
7
+ export type SearchHistoryByLocale = Record<string, History[]>
4
8
 
5
9
  export const searchHistoryStore = createStore(
6
- [] as History[],
10
+ {} as SearchHistoryByLocale,
7
11
  `fs::searchHistory`
8
12
  )
9
13
 
10
14
  const MAX_HISTORY_SIZE = 4
15
+ const DEFAULT_LOCALE = config.localization.enabled
16
+ ? config.localization.defaultLocale
17
+ : config.session.locale
11
18
 
12
19
  export interface History {
13
20
  term: string
14
21
  path: string
15
22
  }
16
23
 
24
+ function migrateSearchHistory(value: unknown): SearchHistoryByLocale {
25
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
26
+ return value as SearchHistoryByLocale
27
+ }
28
+ if (Array.isArray(value) && value.length > 0) {
29
+ return { [DEFAULT_LOCALE]: value as History[] }
30
+ }
31
+ return {}
32
+ }
33
+
17
34
  export default function useSearchHistory(
18
35
  maxHistorySize: number = MAX_HISTORY_SIZE
19
36
  ) {
20
- const searchHistory = useStore(searchHistoryStore)
37
+ const locale = useSession()?.locale ?? DEFAULT_LOCALE
38
+ const rawStore = useStore(searchHistoryStore)
39
+
40
+ const byLocale = useMemo(() => migrateSearchHistory(rawStore), [rawStore])
41
+
42
+ useEffect(() => {
43
+ if (Array.isArray(rawStore)) {
44
+ searchHistoryStore.set(migrateSearchHistory(rawStore))
45
+ }
46
+ }, [rawStore])
47
+
48
+ const searchHistory = byLocale[locale] ?? []
21
49
 
22
50
  function addToSearchHistory(newHistory: History) {
23
51
  const set = new Set<string>()
24
- const newHistoryArray = [newHistory, ...searchHistory]
25
- .slice(0, maxHistorySize)
52
+ const current = byLocale[locale] ?? []
53
+ const newHistoryArray = [newHistory, ...current]
26
54
  .filter((item) => !set.has(item.term) && set.add(item.term), set)
55
+ .slice(0, maxHistorySize)
27
56
 
28
- searchHistoryStore.set(newHistoryArray)
57
+ searchHistoryStore.set({
58
+ ...byLocale,
59
+ [locale]: newHistoryArray,
60
+ })
29
61
  }
30
62
 
31
63
  function clearSearchHistory() {
32
- searchHistoryStore.set([])
64
+ const next = { ...byLocale }
65
+ delete next[locale]
66
+ searchHistoryStore.set(Object.keys(next).length > 0 ? next : {})
33
67
  }
34
68
 
35
69
  return {
@@ -8,6 +8,7 @@ import type {
8
8
  ValidateSessionMutationVariables,
9
9
  } from '@generated/graphql'
10
10
  import deepEqual from 'fast-deep-equal'
11
+ import { filterChannel } from 'src/utils/utilities'
11
12
  import storeConfig from '../../../discovery.config'
12
13
  import {
13
14
  isRefreshTokenSuccessful,
@@ -15,6 +16,7 @@ import {
15
16
  } from '../account/refreshToken'
16
17
  import { cartStore } from '../cart'
17
18
  import { request } from '../graphql/request'
19
+ import { getSettings } from '../localization/useLocalizationConfig'
18
20
  import { createValidationStore, useStore } from '../useStore'
19
21
  import { getPostalCode } from '../userLocation/index'
20
22
  import { RELOAD_AFTER_LOGOUT_KEY, SESSION_READY_KEY } from './storageKeys'
@@ -138,6 +140,24 @@ export const validateSession = async (session: Session) => {
138
140
  session = refreshed
139
141
  }
140
142
 
143
+ if (storeConfig.localization?.enabled) {
144
+ const settings = getSettings()
145
+ const newChanel = JSON.stringify({
146
+ ...(JSON.parse(session.channel ?? '{}') ?? {}),
147
+ salesChannel: settings.salesChannel,
148
+ })
149
+
150
+ if (
151
+ newChanel !== session.channel ||
152
+ settings.locale !== session.locale ||
153
+ deepEqual(settings.currency, session.currency) === false
154
+ ) {
155
+ session.locale = settings.locale
156
+ session.currency = settings.currency
157
+ session.channel = newChanel
158
+ }
159
+ }
160
+
141
161
  // If deliveryPromise is enabled and there is no postalCode in the session
142
162
  if (
143
163
  storeConfig.deliveryPromise?.enabled &&
@@ -253,9 +273,7 @@ export const useSession = ({ filter }: SessionOptions = { filter: true }) => {
253
273
  let { channel, ...session } = resultSessionStore ?? currentSessionStore
254
274
 
255
275
  if (filter) {
256
- const { hasOnlyDefaultSalesChannel, ...filteredChannel } =
257
- JSON.parse(channel)
258
- channel = JSON.stringify(filteredChannel)
276
+ channel = filterChannel(channel ?? '')
259
277
  }
260
278
 
261
279
  return useMemo(
@@ -99,7 +99,15 @@ const reducer = (state: State, action: Action) => {
99
99
  }
100
100
  }
101
101
 
102
- export const useShippingSimulation = (shippingItem: ProductShippingInfo) => {
102
+ interface UseShippingSimulationOptions {
103
+ shippingItem: ProductShippingInfo
104
+ invalidPostalCodeErrorMessage?: string
105
+ }
106
+
107
+ export const useShippingSimulation = ({
108
+ shippingItem,
109
+ invalidPostalCodeErrorMessage,
110
+ }: UseShippingSimulationOptions) => {
103
111
  const [{ input, shippingSimulation }, dispatch] = useReducer(
104
112
  reducer,
105
113
  null,
@@ -172,7 +180,7 @@ export const useShippingSimulation = (shippingItem: ProductShippingInfo) => {
172
180
  type: 'onError',
173
181
  payload: {
174
182
  displayClearButton: true,
175
- errorMessage: 'You entered an invalid Postal Code',
183
+ errorMessage: invalidPostalCodeErrorMessage,
176
184
  },
177
185
  })
178
186
  }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "strict": true
5
+ }
6
+ }
@@ -0,0 +1,48 @@
1
+ import storeConfig from 'discovery.config'
2
+ import { useRouter } from 'next/router'
3
+ import { useCallback } from 'react'
4
+ import {
5
+ addCustomPathPrefix,
6
+ extractCustomPathPrefix,
7
+ } from 'src/utils/localization/bindingPaths'
8
+
9
+ /**
10
+ * Hook that centralizes link resolution with custom path prefix (i18n).
11
+ * Use resolveLink(href) to get the href with the current locale's custom path applied when applicable.
12
+ */
13
+ export function useLink() {
14
+ const router = useRouter()
15
+
16
+ const resolveLink = useCallback(
17
+ (href: string | undefined): string | undefined => {
18
+ if (href == null || href === '') {
19
+ return undefined
20
+ }
21
+ if (href.startsWith('/') && !href.startsWith('//')) {
22
+ const asPath = router.asPath ?? ''
23
+ const withCustomPath = addCustomPathPrefix(href, asPath)
24
+ // On a subdomain, router.defaultLocale is set to the domain's locale (e.g., fr-FR).
25
+ // Using the global config default (e.g., en-US) would incorrectly prepend /fr-FR/ to every link, breaking navigation.
26
+ const defaultLocale =
27
+ router.defaultLocale ?? storeConfig.localization?.defaultLocale
28
+ // Check if current page has a custom path prefix
29
+ const onCustomPath = extractCustomPathPrefix(asPath) !== null
30
+ // Only add Next.js locale when no custom path was applied AND we're not on a custom-path page
31
+ if (
32
+ storeConfig.localization?.enabled &&
33
+ router.locale &&
34
+ defaultLocale &&
35
+ router.locale !== defaultLocale &&
36
+ !onCustomPath
37
+ ) {
38
+ return `/${router.locale}${href}`
39
+ }
40
+ return withCustomPath
41
+ }
42
+ return href
43
+ },
44
+ [router.asPath, router.locale]
45
+ )
46
+
47
+ return { resolveLink }
48
+ }
@@ -7,11 +7,51 @@ type InjectGlobalSectionsProps = {
7
7
  globalSectionsFooter: GlobalSectionsData
8
8
  }
9
9
 
10
+ function createMinimalGlobalSections({
11
+ globalSectionsHeader,
12
+ globalSectionsFooter,
13
+ settings,
14
+ }: {
15
+ globalSectionsHeader: GlobalSectionsData
16
+ globalSectionsFooter: GlobalSectionsData
17
+ settings?: any
18
+ }): GlobalSectionsData {
19
+ const headerSections = globalSectionsHeader?.sections || []
20
+ const footerSections = globalSectionsFooter?.sections || []
21
+
22
+ return {
23
+ sections: [
24
+ ...headerSections,
25
+ {
26
+ name: 'Children',
27
+ data: {},
28
+ },
29
+ ...footerSections,
30
+ ],
31
+ settings: settings || {},
32
+ }
33
+ }
34
+
10
35
  export function injectGlobalSections({
11
36
  globalSections,
12
37
  globalSectionsHeader,
13
38
  globalSectionsFooter,
14
39
  }: InjectGlobalSectionsProps) {
40
+ if (
41
+ !globalSections ||
42
+ !globalSections.sections ||
43
+ globalSections.sections.length === 0
44
+ ) {
45
+ console.warn(
46
+ 'Global Sections content type was not found or has no sections. Returning minimal structure for development.'
47
+ )
48
+ return createMinimalGlobalSections({
49
+ globalSectionsHeader,
50
+ globalSectionsFooter,
51
+ settings: globalSections?.settings,
52
+ })
53
+ }
54
+
15
55
  const childrenIndex = globalSections.sections.findIndex(
16
56
  (section) => section.name === 'Children'
17
57
  )
@@ -1,7 +1,8 @@
1
- import type { ContentData, ContentTypeOptions, Locator } from '@vtex/client-cms'
1
+ import type { ContentData, Locator } from '@vtex/client-cms'
2
2
  import ClientCMS from '@vtex/client-cms'
3
3
 
4
4
  import MultipleContentError from 'src/sdk/error/MultipleContentError'
5
+ import { getStoreURL } from 'src/sdk/localization/useLocalizationConfig'
5
6
  import { sanitizeHost } from 'src/utils/utilities'
6
7
  import config from '../../../discovery.config'
7
8
 
@@ -9,25 +10,32 @@ export type Options =
9
10
  | Locator
10
11
  | {
11
12
  contentType: string
12
- filters?: Partial<ContentTypeOptions>
13
+ filters?: Record<string, string>
13
14
  }
14
15
 
15
16
  type ProductGallerySettings = {
17
+ productGallery: {
18
+ itemsPerPage: number
19
+ sortBySelection: string
20
+ }
21
+ }
22
+
23
+ export type SearchSettings = {
16
24
  settings: {
17
- productGallery: {
18
- itemsPerPage: number
19
- sortBySelection: string
25
+ seo: {
26
+ titleTemplate?: string
20
27
  }
21
- }
28
+ } & ProductGallerySettings
22
29
  }
23
30
 
24
- export type SearchContentType = ContentData & ProductGallerySettings
31
+ export type SearchContentType = ContentData & SearchSettings
25
32
 
26
33
  export type PageContentType = ContentData & {
27
34
  settings: {
28
35
  seo: {
29
36
  slug: string
30
37
  title: string
38
+ titleTemplate?: string
31
39
  description: string
32
40
  canonical?: string
33
41
  name?: string
@@ -68,7 +76,7 @@ export const clientCMS = new ClientCMS({
68
76
  tenant: config.api.storeId,
69
77
  builder:
70
78
  (config.contentSource as Record<string, string>)?.project ?? 'faststore',
71
- host: sanitizeHost(config.storeUrl),
79
+ host: sanitizeHost(new URL(getStoreURL()).origin),
72
80
  })
73
81
 
74
82
  export const getCMSPage = async (
@@ -86,7 +94,7 @@ export const getCMSPage = async (
86
94
  const perPage = 10
87
95
  const response = await cmsClient.getCMSPagesByContentType(
88
96
  options.contentType,
89
- { ...options.filters, page: page, perPage }
97
+ { filters: options.filters, page: page, perPage }
90
98
  )
91
99
 
92
100
  pages.push(...response.data)
@@ -101,7 +109,7 @@ export const getCMSPage = async (
101
109
  const restOfPages = await Promise.all(
102
110
  pagesToFetch.map((i) =>
103
111
  cmsClient.getCMSPagesByContentType(options.contentType, {
104
- ...options.filters,
112
+ filters: options.filters,
105
113
  page: i,
106
114
  perPage,
107
115
  })