@faststore/core 3.98.0-dev.0 → 3.98.0-dev.10

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 (378) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +124 -123
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/config.json +3 -3
  5. package/.next/cache/webpack/client-production/0.pack +0 -0
  6. package/.next/cache/webpack/client-production/index.pack +0 -0
  7. package/.next/cache/webpack/server-production/0.pack +0 -0
  8. package/.next/cache/webpack/server-production/index.pack +0 -0
  9. package/.next/next-minimal-server.js.nft.json +1 -1
  10. package/.next/next-server.js.nft.json +1 -1
  11. package/.next/prerender-manifest.js +1 -1
  12. package/.next/prerender-manifest.json +1 -1
  13. package/.next/react-loadable-manifest.json +167 -163
  14. package/.next/required-server-files.json +1 -1
  15. package/.next/routes-manifest.json +1 -1
  16. package/.next/server/chunks/{5796.js → 1027.js} +1 -1
  17. package/.next/server/chunks/1197.js +1 -0
  18. package/.next/server/chunks/{3483.js → 1313.js} +1 -1
  19. package/.next/server/chunks/1419.js +1 -0
  20. package/.next/server/chunks/1576.js +1 -0
  21. package/.next/server/chunks/{7275.js → 1588.js} +1 -1
  22. package/.next/server/chunks/1741.js +3 -0
  23. package/.next/server/chunks/221.js +1 -0
  24. package/.next/server/chunks/2259.js +9 -0
  25. package/.next/server/chunks/2513.js +1 -0
  26. package/.next/server/chunks/2955.js +1 -0
  27. package/.next/server/chunks/3114.js +1 -0
  28. package/.next/server/chunks/3327.js +1 -0
  29. package/.next/server/chunks/3488.js +1 -0
  30. package/.next/server/chunks/{1917.js → 3513.js} +1 -1
  31. package/.next/server/chunks/3683.js +1 -0
  32. package/.next/server/chunks/{8563.js → 3724.js} +1 -1
  33. package/.next/server/chunks/3977.js +1 -0
  34. package/.next/server/chunks/426.js +1 -0
  35. package/.next/server/chunks/4573.js +1 -0
  36. package/.next/server/chunks/4681.js +1 -0
  37. package/.next/server/chunks/5133.js +3 -0
  38. package/.next/server/chunks/5212.js +7 -0
  39. package/.next/server/chunks/5608.js +1 -0
  40. package/.next/server/chunks/5628.js +12 -0
  41. package/.next/server/chunks/{1607.js → 5764.js} +1 -1
  42. package/.next/server/chunks/{9740.js → 6259.js} +1 -1
  43. package/.next/server/chunks/6698.js +1 -1
  44. package/.next/server/chunks/689.js +1 -0
  45. package/.next/server/chunks/6952.js +1 -0
  46. package/.next/server/chunks/7121.js +1 -0
  47. package/.next/server/chunks/7371.js +1 -1
  48. package/.next/server/chunks/7417.js +1 -0
  49. package/.next/server/chunks/{1280.js → 7722.js} +1 -1
  50. package/.next/server/chunks/7796.js +1 -0
  51. package/.next/server/chunks/7956.js +1 -0
  52. package/.next/server/chunks/{6804.js → 7976.js} +3 -3
  53. package/.next/server/chunks/{9985.js → 8146.js} +1 -1
  54. package/.next/server/chunks/8290.js +1 -0
  55. package/.next/server/chunks/8376.js +13 -0
  56. package/.next/server/chunks/8466.js +6 -0
  57. package/.next/server/chunks/8569.js +1 -1
  58. package/.next/server/chunks/8659.js +1 -0
  59. package/.next/server/chunks/8741.js +1 -0
  60. package/.next/server/chunks/8971.js +493 -0
  61. package/.next/server/chunks/9088.js +1 -1
  62. package/.next/server/chunks/9237.js +1 -1
  63. package/.next/server/chunks/9374.js +13 -0
  64. package/.next/server/chunks/{8068.js → 9425.js} +1 -1
  65. package/.next/server/chunks/{UINavbarSlider.js → 9984.js} +1 -1
  66. package/.next/server/chunks/9986.js +1 -0
  67. package/.next/server/chunks/ButtonSignIn.js +1 -1
  68. package/.next/server/chunks/FilterSkeleton.js +1 -1
  69. package/.next/server/chunks/ScrollToTopButton.js +1 -1
  70. package/.next/server/chunks/UIBannerText.js +1 -1
  71. package/.next/server/chunks/UISKUMatrixSidebar.js +1 -1
  72. package/.next/server/functions-config-manifest.json +1 -1
  73. package/.next/server/middleware-build-manifest.js +1 -1
  74. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  75. package/.next/server/pages/404.js +1 -1
  76. package/.next/server/pages/404.js.nft.json +1 -1
  77. package/.next/server/pages/500.js +1 -1
  78. package/.next/server/pages/500.js.nft.json +1 -1
  79. package/.next/server/pages/[...slug].js +1 -1
  80. package/.next/server/pages/[...slug].js.nft.json +1 -1
  81. package/.next/server/pages/[slug]/p.js +1 -1
  82. package/.next/server/pages/[slug]/p.js.nft.json +1 -1
  83. package/.next/server/pages/_app.js +1 -1
  84. package/.next/server/pages/_app.js.nft.json +1 -1
  85. package/.next/server/pages/_document.js +1 -1
  86. package/.next/server/pages/_document.js.nft.json +1 -1
  87. package/.next/server/pages/_error.js +1 -1
  88. package/.next/server/pages/_error.js.nft.json +1 -1
  89. package/.next/server/pages/api/fs/logout.js +1 -1
  90. package/.next/server/pages/api/fs/logout.js.nft.json +1 -1
  91. package/.next/server/pages/api/graphql.js +3 -3
  92. package/.next/server/pages/api/graphql.js.nft.json +1 -1
  93. package/.next/server/pages/api/health/live.js +1 -1
  94. package/.next/server/pages/api/health/live.js.nft.json +1 -1
  95. package/.next/server/pages/api/health/ready.js +1 -1
  96. package/.next/server/pages/api/health/ready.js.nft.json +1 -1
  97. package/.next/server/pages/api/preview.js +1 -1
  98. package/.next/server/pages/api/preview.js.nft.json +1 -1
  99. package/.next/server/pages/checkout.js +1 -1
  100. package/.next/server/pages/checkout.js.nft.json +1 -1
  101. package/.next/server/pages/en-US/404.html +2 -2
  102. package/.next/server/pages/en-US/404.json +1 -1
  103. package/.next/server/pages/en-US/500.html +2 -2
  104. package/.next/server/pages/en-US/500.json +1 -1
  105. package/.next/server/pages/en-US/checkout.html +2 -2
  106. package/.next/server/pages/en-US/checkout.json +1 -1
  107. package/.next/server/pages/en-US/login.html +2 -2
  108. package/.next/server/pages/en-US/login.json +1 -1
  109. package/.next/server/pages/en-US/s.html +2 -2
  110. package/.next/server/pages/en-US/s.json +1 -1
  111. package/.next/server/pages/en-US.html +2 -2
  112. package/.next/server/pages/en-US.json +1 -1
  113. package/.next/server/pages/index.js +1 -1
  114. package/.next/server/pages/index.js.nft.json +1 -1
  115. package/.next/server/pages/login.js +1 -1
  116. package/.next/server/pages/login.js.nft.json +1 -1
  117. package/.next/server/pages/pvt/account/403.js +1 -1
  118. package/.next/server/pages/pvt/account/403.js.nft.json +1 -1
  119. package/.next/server/pages/pvt/account/404.js +1 -1
  120. package/.next/server/pages/pvt/account/404.js.nft.json +1 -1
  121. package/.next/server/pages/pvt/account/[...unknown].js +1 -1
  122. package/.next/server/pages/pvt/account/[...unknown].js.nft.json +1 -1
  123. package/.next/server/pages/pvt/account/orders/[id].js +1 -1
  124. package/.next/server/pages/pvt/account/orders/[id].js.nft.json +1 -1
  125. package/.next/server/pages/pvt/account/orders.js +1 -1
  126. package/.next/server/pages/pvt/account/orders.js.nft.json +1 -1
  127. package/.next/server/pages/pvt/account/profile.js +1 -1
  128. package/.next/server/pages/pvt/account/profile.js.nft.json +1 -1
  129. package/.next/server/pages/pvt/account/security.js +1 -1
  130. package/.next/server/pages/pvt/account/security.js.nft.json +1 -1
  131. package/.next/server/pages/pvt/account/user-details.js +1 -1
  132. package/.next/server/pages/pvt/account/user-details.js.nft.json +1 -1
  133. package/.next/server/pages/pvt/account.js +1 -1
  134. package/.next/server/pages/pvt/account.js.nft.json +1 -1
  135. package/.next/server/pages/s.js +1 -1
  136. package/.next/server/pages/s.js.nft.json +1 -1
  137. package/.next/server/pages-manifest.json +1 -1
  138. package/.next/server/webpack-runtime.js +1 -1
  139. package/.next/static/Xu5Fn6_Qwp_x6LicEI8BU/_buildManifest.js +1 -0
  140. package/.next/static/chunks/{5796.4351370494d8b8b6.js → 1027.f17a7c96c17ce487.js} +1 -1
  141. package/.next/static/chunks/1313.bba028de90630608.js +1 -0
  142. package/.next/static/chunks/1756.89b7f413bb26ba74.js +1 -0
  143. package/.next/static/chunks/{8325.dabe9aa22eaadeed.js → 1911.fb72de1df3c3715c.js} +1 -1
  144. package/.next/static/chunks/2221-f8edfdaa4839bdf0.js +2 -0
  145. package/.next/static/chunks/2564.273fd8b0db75b1c4.js +1 -0
  146. package/.next/static/chunks/2811.cf089090a8b79215.js +1 -0
  147. package/.next/static/chunks/346.2840f007e6d1054c.js +1 -0
  148. package/.next/static/chunks/3496.bcb4d219501a8b6b.js +1 -0
  149. package/.next/static/chunks/3753-74460a0793c0a75c.js +8 -0
  150. package/.next/static/chunks/3802.1e0df8a20802da16.js +1 -0
  151. package/.next/static/chunks/3883-ebdbb60b50a90c59.js +28 -0
  152. package/.next/static/chunks/4436.9b2b6e1c3f79424d.js +1 -0
  153. package/.next/static/chunks/4681.318feb830c746e3b.js +1 -0
  154. package/.next/static/chunks/484.9fdcaa9ffd8dac08.js +1 -0
  155. package/.next/static/chunks/6218.e8ba8bf8602ec880.js +1 -0
  156. package/.next/static/chunks/{6393.e4b26fee060438d6.js → 6393.f5f13a004beeef40.js} +1 -1
  157. package/.next/static/chunks/6656-efc464f20ffeaa51.js +1 -0
  158. package/.next/static/chunks/6797-ff5656c8624c4265.js +1 -0
  159. package/.next/static/chunks/6943.6bc97e925b54493d.js +1 -0
  160. package/.next/static/chunks/7417.55a6e20779dd3702.js +1 -0
  161. package/.next/static/chunks/7534.ee76e63d58ddd222.js +1 -0
  162. package/.next/static/chunks/7796.a30626656a270831.js +1 -0
  163. package/.next/static/chunks/9105.354374e349da85cb.js +1 -0
  164. package/.next/static/chunks/9222.04daf7868c957e52.js +1 -0
  165. package/.next/static/chunks/{9237.7555603703f81bf7.js → 9237.2d7e1a4978875414.js} +1 -1
  166. package/.next/static/chunks/9399.199f217093e4af1e.js +1 -0
  167. package/.next/static/chunks/{8068.43663fb64762f7b8.js → 9425.9d8b3da847111f21.js} +1 -1
  168. package/.next/static/chunks/9701.f9a0bfffba8807dc.js +1 -0
  169. package/.next/static/chunks/BannerNewsletter.b5770016d20acfd2.js +1 -0
  170. package/.next/static/chunks/{BannerText.4061ccfc191e6b96.js → BannerText.5ba50fbe683158ec.js} +1 -1
  171. package/.next/static/chunks/{ButtonSignIn.f6e210eaca873e48.js → ButtonSignIn.639d8dfc65ded368.js} +1 -1
  172. package/.next/static/chunks/CartItem.3c2ceb3a4ee542bc.js +1 -0
  173. package/.next/static/chunks/CartSidebar.89b0dd6237c025ec.js +1 -0
  174. package/.next/static/chunks/{EmptyCart.320e2f94a0d5e6b1.js → EmptyCart.aa60d42ae8eb5264.js} +1 -1
  175. package/.next/static/chunks/{FilterSkeleton.7ab99e28f92341c9.js → FilterSkeleton.8f1b651c40e06f0b.js} +1 -1
  176. package/.next/static/chunks/Footer.cd83c4dc0252494a.js +1 -0
  177. package/.next/static/chunks/Gift.4c97f836f82d5ebe.js +1 -0
  178. package/.next/static/chunks/Newsletter.bdec43379ca9191a.js +1 -0
  179. package/.next/static/chunks/OrderSummary.994b7314f2d004af.js +1 -0
  180. package/.next/static/chunks/PreviewTag.696854f6690e1b9e.js +1 -0
  181. package/.next/static/chunks/ProductShelf.fe1f19bc68859695.js +1 -0
  182. package/.next/static/chunks/ProductTiles.2c63ae178a75d5b6.js +1 -0
  183. package/.next/static/chunks/{RegionModal.a7be32d2d7832ba4.js → RegionModal.fbbdd54ee2422522.js} +1 -1
  184. package/.next/static/chunks/RegionSlider.49e558b340a5506a.js +1 -0
  185. package/.next/static/chunks/{ScrollToTopButton.c15431f2e8bb93ef.js → ScrollToTopButton.55e3a1233d04b8eb.js} +1 -1
  186. package/.next/static/chunks/ShoppingAssistant.8772fe90bd678202.js +1 -0
  187. package/.next/static/chunks/Toast.f083d9966a9a181e.js +1 -0
  188. package/.next/static/chunks/UISKUMatrixSidebar.01f8f5222dcdf80f.js +1 -0
  189. package/.next/static/chunks/main-edeb2c6a5c48bb3f.js +1 -0
  190. package/.next/static/chunks/pages/404-1e8f91fa1bca3ab8.js +1 -0
  191. package/.next/static/chunks/pages/500-f21feacbb9810e94.js +1 -0
  192. package/.next/static/chunks/pages/[...slug]-400781188d59cfd6.js +1 -0
  193. package/.next/static/chunks/pages/[slug]/p-f324b592d1c566b9.js +1 -0
  194. package/.next/static/chunks/pages/_app-735c745509e1e8d6.js +1 -0
  195. package/.next/static/chunks/pages/{_error-2b0148be56a716e9.js → _error-464097ff69347627.js} +1 -1
  196. package/.next/static/chunks/pages/checkout-6076b4baf0ca1aa6.js +1 -0
  197. package/.next/static/chunks/pages/index-3266ece2e885bb3a.js +1 -0
  198. package/.next/static/chunks/pages/login-add3b376f68ce39a.js +1 -0
  199. package/.next/static/chunks/pages/pvt/account/403-d44b70591d2c86dc.js +1 -0
  200. package/.next/static/chunks/pages/pvt/account/404-646fb609f579101e.js +1 -0
  201. package/.next/static/chunks/pages/pvt/account/[...unknown]-3fb3963ca3d77c0b.js +1 -0
  202. package/.next/static/chunks/pages/pvt/account/orders/[id]-cda2266c9693d552.js +1 -0
  203. package/.next/static/chunks/pages/pvt/account/orders-ec545a2679db206e.js +1 -0
  204. package/.next/static/chunks/pages/pvt/account/profile-27164b37098c553f.js +1 -0
  205. package/.next/static/chunks/pages/pvt/account/security-4bd3e75771a120ec.js +1 -0
  206. package/.next/static/chunks/pages/pvt/account/user-details-a48a44dfdc07c1e9.js +1 -0
  207. package/.next/static/chunks/pages/pvt/account-5a6dcae3b380b672.js +1 -0
  208. package/.next/static/chunks/pages/s-0fe527a651dd5989.js +1 -0
  209. package/.next/static/chunks/webpack-d3e4f545845241c4.js +1 -0
  210. package/.next/static/css/094ad5cc00c74e64.css +1 -0
  211. package/.next/static/css/{b684b347c5cc6514.css → 1154064b68a7f35e.css} +1 -1
  212. package/.next/static/css/1b7e34d448a42825.css +1 -0
  213. package/.next/static/css/23857075311e4d06.css +1 -0
  214. package/.next/static/css/482e6fa149885bc2.css +1 -0
  215. package/.next/static/css/4b2af1aaeb961465.css +1 -0
  216. package/.next/static/css/{837662922091162f.css → 52ab64b6a2b14e3e.css} +1 -1
  217. package/.next/static/css/5cd37b7508dd5190.css +1 -0
  218. package/.next/static/css/72f154a00f1cf621.css +1 -0
  219. package/.next/static/css/8a513f4b536b0ab0.css +1 -0
  220. package/.next/static/css/9b4c21dcd3bc4a17.css +1 -0
  221. package/.next/static/css/d0930b8076866831.css +1 -0
  222. package/.next/static/css/e028eb9f46d42611.css +1 -0
  223. package/.next/static/css/e68c313e4ce2fd1b.css +1 -0
  224. package/.next/static/css/f16438bcf4508fb3.css +1 -0
  225. package/.next/trace +142 -140
  226. package/.turbo/turbo-build.log +45 -65
  227. package/.turbo/turbo-test.log +6 -6
  228. package/@generated/gql.ts +22 -14
  229. package/@generated/graphql.ts +148 -55
  230. package/@generated/persisted-documents.json +5 -4
  231. package/@generated/schema.graphql +4 -0
  232. package/CHANGELOG.md +60 -4
  233. package/cms/faststore/base.jsonc +3 -3
  234. package/cms/faststore/components/cms_component__productshelf.jsonc +2 -2
  235. package/cms/faststore/components/cms_component__producttiles.jsonc +2 -2
  236. package/cms/faststore/schema.json +2510 -2482
  237. package/cms/faststore/sections.json +485 -4
  238. package/cypress/tsconfig.json +7 -0
  239. package/discovery.config.default.js +2 -0
  240. package/jest.config.js +3 -0
  241. package/next.config.js +4 -0
  242. package/package.json +8 -7
  243. package/public/icons.svg +62 -0
  244. package/src/components/ThirdPartyScripts/index.ts +1 -0
  245. package/src/components/ThirdPartyScripts/useShoppingAssistant.tsx +30 -0
  246. package/src/components/account/MyAccountDrawer/OrganizationDrawer/OrganizationDrawer.tsx +27 -18
  247. package/src/components/account/MyAccountDrawer/OrganizationDrawer/useReloadAfterLogoutReturn.ts +75 -0
  248. package/src/components/cms/global/Components.ts +8 -0
  249. package/src/components/product/ProductGrid/ProductGrid.tsx +26 -1
  250. package/src/components/search/SearchDropdown/SearchDropdown.tsx +11 -2
  251. package/src/components/search/SearchInput/SearchInput.tsx +492 -5
  252. package/src/components/sections/Navbar/Navbar.tsx +67 -0
  253. package/src/components/sections/Navbar/section.module.scss +3 -0
  254. package/src/components/sections/ProductDetails/ProductDetails.tsx +1 -0
  255. package/src/components/sections/ShoppingAssistant/ShoppingAssistant.tsx +24 -0
  256. package/src/components/sections/ShoppingAssistant/index.ts +1 -0
  257. package/src/components/sections/ShoppingAssistant/section.module.scss +5 -0
  258. package/src/components/templates/ProductListingPage/ProductListing.tsx +1 -1
  259. package/src/components/ui/ProductGallery/ProductGalleryPage.tsx +17 -0
  260. package/src/pages/[slug]/p.tsx +2 -0
  261. package/src/pages/_app.tsx +2 -0
  262. package/src/sdk/graphql/request.ts +1 -1
  263. package/src/sdk/graphql/useQuery.ts +23 -6
  264. package/src/sdk/product/convertProductToQuickOrder.ts +85 -0
  265. package/src/sdk/product/useBulkProductsQuery.ts +128 -0
  266. package/src/sdk/product/usePageProductsQuery.ts +11 -9
  267. package/src/sdk/search/useSuggestions.ts +1 -0
  268. package/src/styles/global/index.scss +2 -1
  269. package/src/utils/cookieCacheBusting.ts +35 -41
  270. package/src/utils/utilities.ts +62 -0
  271. package/test/tsconfig.json +7 -0
  272. package/test/utils/cookieCacheBusting.test.ts +54 -47
  273. package/.next/server/chunks/1554.js +0 -1
  274. package/.next/server/chunks/1780.js +0 -1
  275. package/.next/server/chunks/2249.js +0 -1
  276. package/.next/server/chunks/2430.js +0 -1
  277. package/.next/server/chunks/2445.js +0 -12
  278. package/.next/server/chunks/2570.js +0 -1
  279. package/.next/server/chunks/294.js +0 -1
  280. package/.next/server/chunks/3029.js +0 -1
  281. package/.next/server/chunks/3836.js +0 -1
  282. package/.next/server/chunks/3890.js +0 -492
  283. package/.next/server/chunks/3945.js +0 -1
  284. package/.next/server/chunks/3951.js +0 -7
  285. package/.next/server/chunks/4194.js +0 -1
  286. package/.next/server/chunks/4365.js +0 -1
  287. package/.next/server/chunks/4803.js +0 -1
  288. package/.next/server/chunks/4913.js +0 -13
  289. package/.next/server/chunks/5683.js +0 -1
  290. package/.next/server/chunks/5723.js +0 -13
  291. package/.next/server/chunks/6789.js +0 -1
  292. package/.next/server/chunks/6886.js +0 -1
  293. package/.next/server/chunks/7098.js +0 -9
  294. package/.next/server/chunks/7692.js +0 -1
  295. package/.next/server/chunks/772.js +0 -6
  296. package/.next/server/chunks/7799.js +0 -1
  297. package/.next/server/chunks/83.js +0 -1
  298. package/.next/server/chunks/8307.js +0 -1
  299. package/.next/server/chunks/8482.js +0 -1
  300. package/.next/server/chunks/8598.js +0 -1
  301. package/.next/server/chunks/8687.js +0 -1
  302. package/.next/server/chunks/870.js +0 -1
  303. package/.next/server/chunks/9117.js +0 -1
  304. package/.next/server/chunks/948.js +0 -2
  305. package/.next/server/chunks/9563.js +0 -3
  306. package/.next/server/chunks/9853.js +0 -1
  307. package/.next/server/chunks/9990.js +0 -1
  308. package/.next/static/bRIIH80orCsnMQY0jzRSl/_buildManifest.js +0 -1
  309. package/.next/static/chunks/1208-9118a8f14ecf05c8.js +0 -8
  310. package/.next/static/chunks/1841.a1b15f2c88e02d32.js +0 -1
  311. package/.next/static/chunks/2284.dffe7b0e5a5bfb4a.js +0 -1
  312. package/.next/static/chunks/2500.d6beb5af6ee00a9e.js +0 -1
  313. package/.next/static/chunks/2851.e68ed3c8d27a032a.js +0 -1
  314. package/.next/static/chunks/3155.7bc4c730a79d9ecb.js +0 -1
  315. package/.next/static/chunks/3399.3e1f685c992c345b.js +0 -1
  316. package/.next/static/chunks/3483.ef53d632a763da3f.js +0 -1
  317. package/.next/static/chunks/349.235b18ceb82aa256.js +0 -1
  318. package/.next/static/chunks/3836.612763339fc4c64c.js +0 -1
  319. package/.next/static/chunks/4803.9822f0b7e469b933.js +0 -1
  320. package/.next/static/chunks/5859.3bc094416cffd966.js +0 -1
  321. package/.next/static/chunks/6031-b0b111f48a7d504d.js +0 -28
  322. package/.next/static/chunks/6700.a72869377e81146c.js +0 -1
  323. package/.next/static/chunks/6789.960162355435a81d.js +0 -1
  324. package/.next/static/chunks/7191-5ede6e7ef625ea77.js +0 -1
  325. package/.next/static/chunks/7522-9010743f5d7e8aca.js +0 -1
  326. package/.next/static/chunks/7692.8d5bf4560341a2f6.js +0 -1
  327. package/.next/static/chunks/83.98ce246c274ee7e4.js +0 -1
  328. package/.next/static/chunks/9173-ab3c4d9d8f978c4b.js +0 -1
  329. package/.next/static/chunks/9399.48251a278809f7d3.js +0 -1
  330. package/.next/static/chunks/941.3e2782ab9c490eb0.js +0 -1
  331. package/.next/static/chunks/9465.e09b81f7e6195587.js +0 -1
  332. package/.next/static/chunks/9701.b0e8741551995fbb.js +0 -1
  333. package/.next/static/chunks/9909.787576b171184aa5.js +0 -1
  334. package/.next/static/chunks/BannerNewsletter.90d4a98c15a35cea.js +0 -1
  335. package/.next/static/chunks/CartItem.092df07db9e8b271.js +0 -1
  336. package/.next/static/chunks/CartSidebar.f0c16e2bc6f96e9e.js +0 -1
  337. package/.next/static/chunks/Footer.63a7682a81a96f8e.js +0 -1
  338. package/.next/static/chunks/Gift.08db4da8c89cacf1.js +0 -1
  339. package/.next/static/chunks/Newsletter.dbf35a8ea6d2067e.js +0 -1
  340. package/.next/static/chunks/OrderSummary.f9adad5622605046.js +0 -1
  341. package/.next/static/chunks/PreviewTag.f4f0c8710a7bcad9.js +0 -1
  342. package/.next/static/chunks/ProductShelf.7ebce1c763b4508e.js +0 -1
  343. package/.next/static/chunks/ProductTiles.18f55314e61957f4.js +0 -1
  344. package/.next/static/chunks/RegionSlider.b4dd4e7c0483966d.js +0 -1
  345. package/.next/static/chunks/Toast.2e9b26159af29889.js +0 -1
  346. package/.next/static/chunks/UISKUMatrixSidebar.87ba393b7d738e99.js +0 -1
  347. package/.next/static/chunks/main-ec03882c4375091d.js +0 -1
  348. package/.next/static/chunks/pages/404-4b3f1e22c77f849a.js +0 -1
  349. package/.next/static/chunks/pages/500-bb2de0c11524b2b8.js +0 -1
  350. package/.next/static/chunks/pages/[...slug]-3579b3b8b8309552.js +0 -1
  351. package/.next/static/chunks/pages/[slug]/p-7ac98274c47b0ff4.js +0 -1
  352. package/.next/static/chunks/pages/_app-1595678557980d65.js +0 -1
  353. package/.next/static/chunks/pages/checkout-dc07d72b3514c83d.js +0 -1
  354. package/.next/static/chunks/pages/index-1f8bf0fb351b90f4.js +0 -1
  355. package/.next/static/chunks/pages/login-e97ef92769456bf6.js +0 -1
  356. package/.next/static/chunks/pages/pvt/account/403-91597100f8956385.js +0 -1
  357. package/.next/static/chunks/pages/pvt/account/404-c68124bed7cb7c48.js +0 -1
  358. package/.next/static/chunks/pages/pvt/account/[...unknown]-f80f645594d2740c.js +0 -1
  359. package/.next/static/chunks/pages/pvt/account/orders/[id]-e03ebb0393ac92a2.js +0 -1
  360. package/.next/static/chunks/pages/pvt/account/orders-12a215899ae6f3eb.js +0 -1
  361. package/.next/static/chunks/pages/pvt/account/profile-b6cdbf02d4682544.js +0 -1
  362. package/.next/static/chunks/pages/pvt/account/security-e6289a40e745d3c4.js +0 -1
  363. package/.next/static/chunks/pages/pvt/account/user-details-fba1822e52e7de26.js +0 -1
  364. package/.next/static/chunks/pages/pvt/account-65fefcc699344bdb.js +0 -1
  365. package/.next/static/chunks/pages/s-41cffb20de1d2617.js +0 -1
  366. package/.next/static/chunks/webpack-345c083b2f1f8bb9.js +0 -1
  367. package/.next/static/css/05c399956ff24b77.css +0 -1
  368. package/.next/static/css/08d03445f1797608.css +0 -1
  369. package/.next/static/css/0f070d03aacd9cc5.css +0 -1
  370. package/.next/static/css/0fae3d432331aae9.css +0 -1
  371. package/.next/static/css/0fc6b2ff69142c6a.css +0 -1
  372. package/.next/static/css/31380ebc6e671486.css +0 -1
  373. package/.next/static/css/40a294d0a24ad01d.css +0 -1
  374. package/.next/static/css/47f1b4e8de15d314.css +0 -1
  375. package/.next/static/css/973dd40d4773e8cd.css +0 -1
  376. package/.next/static/css/9d403a1bee48c9fc.css +0 -1
  377. package/.next/static/css/a6a4ebbe01adbbad.css +0 -1
  378. /package/.next/static/{bRIIH80orCsnMQY0jzRSl → Xu5Fn6_Qwp_x6LicEI8BU}/_ssgManifest.js +0 -0
@@ -378,6 +378,7 @@ export const fragment = gql(`
378
378
  priceWithTaxes
379
379
  listPrice
380
380
  listPriceWithTaxes
381
+ quantity
381
382
  seller {
382
383
  identifier
383
384
  }
@@ -0,0 +1,24 @@
1
+ import { useRef } from 'react'
2
+
3
+ import { useShoppingAssistant } from 'src/components/ThirdPartyScripts'
4
+
5
+ import Section from '../Section'
6
+
7
+ import styles from './section.module.scss'
8
+
9
+ const ShoppingAssistant = () => {
10
+ const scriptContainerRef = useRef<HTMLDivElement>(null)
11
+ useShoppingAssistant(scriptContainerRef)
12
+
13
+ return (
14
+ <Section
15
+ className={`${styles.section} section-shopping-assistant layout__section`}
16
+ >
17
+ <div ref={scriptContainerRef} aria-hidden="true" hidden />
18
+ </Section>
19
+ )
20
+ }
21
+
22
+ ShoppingAssistant.$componentKey = 'ShoppingAssistant'
23
+
24
+ export default ShoppingAssistant
@@ -0,0 +1 @@
1
+ export { default } from './ShoppingAssistant'
@@ -0,0 +1,5 @@
1
+ @layer components {
2
+ .section {
3
+ position: relative;
4
+ }
5
+ }
@@ -73,7 +73,7 @@ export default function ProductListing({
73
73
  itemsPerPage,
74
74
  })
75
75
 
76
- const initialPages = { search: server?.search }
76
+ const initialPages = { search: { ...server?.search, searchId: '' } }
77
77
  const { pages, useGalleryPage } = useCreateUseGalleryPage({
78
78
  initialPages,
79
79
  serverManyProductsVariables,
@@ -18,6 +18,20 @@ interface Props {
18
18
  compareLabel?: string
19
19
  }
20
20
 
21
+ function buildExtraProductProps(
22
+ product: Record<string, string>,
23
+ index: number,
24
+ searchId: string
25
+ ) {
26
+ return {
27
+ 'data-af-element': 'search-result',
28
+ 'data-af-onclick': product && !!product.productId,
29
+ 'data-af-search-id': searchId,
30
+ 'data-af-product-position': Number(index ?? 0) + 1, // Product position in Search Analytics starts with 1
31
+ 'data-af-product-id': product && product.productId,
32
+ }
33
+ }
34
+
21
35
  function ProductGalleryPage({
22
36
  page,
23
37
  title,
@@ -30,6 +44,7 @@ function ProductGalleryPage({
30
44
  const { data } = useGalleryPage(page)
31
45
 
32
46
  const products = data?.search?.products?.edges ?? []
47
+ const searchId = data?.search?.searchId
33
48
 
34
49
  return (
35
50
  <Sentinel
@@ -47,6 +62,8 @@ function ProductGalleryPage({
47
62
  productCard={productCard}
48
63
  firstPage={firstPage}
49
64
  title={title}
65
+ searchId={searchId}
66
+ buildExtraProductProps={searchId && buildExtraProductProps}
50
67
  />
51
68
  </Sentinel>
52
69
  )
@@ -208,6 +208,7 @@ function Page({
208
208
  brand={product.brand.name}
209
209
  sku={product.sku}
210
210
  gtin={product.gtin}
211
+ mpn={product.mpn}
211
212
  releaseDate={product.releaseDate}
212
213
  images={product.image.map((img) => img.url)} // Somehow, Google does not understand this valid Schema.org schema, so we need to do conversions
213
214
  offers={offers}
@@ -256,6 +257,7 @@ const query = gql(`
256
257
 
257
258
  sku
258
259
  gtin
260
+ mpn
259
261
  name
260
262
  description
261
263
  releaseDate
@@ -6,6 +6,7 @@ import { useRouter } from 'next/router'
6
6
  import { useSearch } from '@faststore/sdk'
7
7
  import { UIProvider } from '@faststore/ui'
8
8
 
9
+ import { useReloadAfterLogoutReturn } from 'src/components/account/MyAccountDrawer/OrganizationDrawer/useReloadAfterLogoutReturn'
9
10
  import ThirdPartyScripts from 'src/components/ThirdPartyScripts'
10
11
  import Layout from 'src/Layout'
11
12
  import AnalyticsHandler from 'src/sdk/analytics'
@@ -24,6 +25,7 @@ import { ITEMS_PER_PAGE } from 'src/constants'
24
25
 
25
26
  function App({ Component, pageProps }: AppProps) {
26
27
  useGeolocation()
28
+ useReloadAfterLogoutReturn()
27
29
  storeConfig.experimental?.scrollRestoration && useScrollRestoration()
28
30
  const router = useRouter()
29
31
  const { start: startGlobalSearchState } = useSearch()
@@ -29,7 +29,7 @@ export const request = async <Query = unknown, Variables = unknown>(
29
29
  variables: Variables,
30
30
  options?: RequestOptions
31
31
  ) => {
32
- // Get cache busting value based on cookie changes
32
+ // Get cache busting value based person?.id from session
33
33
  const value = getClientCacheBustingValue()
34
34
 
35
35
  const { data, errors } = await baseRequest<Variables, Query>('/api/graphql', {
@@ -1,8 +1,10 @@
1
- import useSWR from 'swr'
2
1
  import type { SWRConfiguration } from 'swr'
2
+ import useSWR from 'swr'
3
+
4
+ import { getClientCacheBustingValue } from 'src/utils/cookieCacheBusting'
3
5
 
4
- import { request } from './request'
5
6
  import type { Operation, RequestOptions } from './request'
7
+ import { request } from './request'
6
8
 
7
9
  export type QueryOptions = SWRConfiguration &
8
10
  RequestOptions & { doNotRun?: boolean }
@@ -12,6 +14,19 @@ export const getKey = <Variables>(
12
14
  variables: Variables
13
15
  ) => `${operationName}::${JSON.stringify(variables)}`
14
16
 
17
+ /**
18
+ * Returns a suffix for the cache key based on auth state (logged-in vs anonymous).
19
+ * This ensures SWR keeps separate cache entries for logged-in and logged-out users,
20
+ * avoiding stale product data (e.g. prices, availability) when switching session state.
21
+ */
22
+ const getSessionCacheKeySuffix = (): string => {
23
+ if (typeof window === 'undefined') {
24
+ return ''
25
+ }
26
+ const value = getClientCacheBustingValue()
27
+ return value ?? ''
28
+ }
29
+
15
30
  export const DEFAULT_OPTIONS = {
16
31
  errorRetryCount: 3,
17
32
  refreshWhenHidden: false,
@@ -27,10 +42,12 @@ export const useQuery = <Data, Variables = Record<string, unknown>>(
27
42
  options?: QueryOptions
28
43
  ) =>
29
44
  useSWR<Data>(
30
- () =>
31
- options?.doNotRun
32
- ? null
33
- : getKey(operation['__meta__']['operationName'], variables),
45
+ () => {
46
+ if (options?.doNotRun) return null
47
+ const baseKey = getKey(operation['__meta__']['operationName'], variables)
48
+ const sessionSuffix = getSessionCacheKeySuffix()
49
+ return `${baseKey}::${sessionSuffix}`
50
+ },
34
51
  {
35
52
  fetcher: () => {
36
53
  return new Promise((resolve) => {
@@ -0,0 +1,85 @@
1
+ import type { Product } from '@faststore/ui'
2
+ import type { ProductDetailsFragment_ProductFragment } from '@generated/graphql'
3
+
4
+ /**
5
+ * Converts a product from the API to the format expected by QuickOrderDrawer
6
+ */
7
+ export const convertProductToQuickOrder = (
8
+ product: ProductDetailsFragment_ProductFragment,
9
+ requestedQuantity: number
10
+ ): Product | null => {
11
+ if (!product || !product.offers || !product.offers.offers.length) {
12
+ return null
13
+ }
14
+
15
+ const offer = product.offers.offers[0]
16
+
17
+ // Determine availability based on the offer's availability field
18
+ // Availability can be 'https://schema.org/InStock' or 'https://schema.org/OutOfStock'
19
+ const isOutOfStock = offer.availability === 'https://schema.org/OutOfStock'
20
+ const isInStock = offer.availability === 'https://schema.org/InStock'
21
+
22
+ // Get inventory quantity from the offer
23
+ // If quantity is not provided, we'll use a default high value when InStock
24
+ // This handles cases where the API doesn't return quantity but marks it as InStock
25
+ const offerQuantity = (offer as { quantity?: number | null }).quantity
26
+ const inventory =
27
+ offerQuantity != null
28
+ ? offerQuantity
29
+ : isInStock
30
+ ? 999999 // Default to high inventory when InStock but quantity not provided
31
+ : 0
32
+
33
+ // Product is available if it's in stock
34
+ // If quantity is provided, we also check it, but availability field takes precedence
35
+ const availability = isInStock ? 'available' : 'outOfStock'
36
+
37
+ // Determine selectedCount and quantityUpdated based on availability and inventory
38
+ let selectedCount: number
39
+ let quantityUpdated: boolean
40
+ const normalizedRequestedQuantity =
41
+ Number.isFinite(requestedQuantity) && requestedQuantity > 0
42
+ ? Math.floor(requestedQuantity)
43
+ : 1
44
+
45
+ if (isOutOfStock) {
46
+ // Out of stock: set quantity to 0
47
+ selectedCount = 0
48
+ quantityUpdated = true
49
+ } else if (inventory === 0) {
50
+ // Inventory is 0 but marked as InStock (edge case): set quantity to 0
51
+ selectedCount = 0
52
+ quantityUpdated = true
53
+ } else if (offerQuantity != null && normalizedRequestedQuantity > inventory) {
54
+ // Quantity is provided and requested quantity exceeds inventory: cap at inventory
55
+ selectedCount = inventory
56
+ quantityUpdated = true
57
+ } else {
58
+ // Requested quantity is within inventory (or quantity not provided): use requested quantity
59
+ selectedCount = normalizedRequestedQuantity
60
+ quantityUpdated = normalizedRequestedQuantity !== requestedQuantity
61
+ }
62
+
63
+ // Get the variant name from allVariantProducts that matches this product's SKU
64
+ // This ensures we use the correct variant name instead of the product name
65
+ const variantProduct =
66
+ product.isVariantOf?.skuVariants?.allVariantProducts?.find(
67
+ (variant) =>
68
+ variant.productID === product.id || variant.productID === product.sku
69
+ )
70
+ const productName = variantProduct?.name ?? product.name
71
+
72
+ return {
73
+ id: product.sku,
74
+ name: productName,
75
+ price: offer.price,
76
+ quantityUpdated,
77
+ image: {
78
+ url: product.image[0]?.url ?? '',
79
+ alternateName: product.image[0]?.alternateName || product.name,
80
+ },
81
+ inventory,
82
+ availability: availability as 'available' | 'outOfStock',
83
+ selectedCount,
84
+ }
85
+ }
@@ -0,0 +1,128 @@
1
+ import { useEffect, useMemo, useState } from 'react'
2
+
3
+ import { gql } from '@generated'
4
+ import type {
5
+ ClientProductQueryQuery,
6
+ ClientProductQueryQueryVariables,
7
+ } from '@generated/graphql'
8
+
9
+ import { request } from '../graphql/request'
10
+ import { useSession } from '../session'
11
+
12
+ // Use the same query as useProductQuery for individual products
13
+ const query = gql(`
14
+ query ClientProductQuery($locator: [IStoreSelectedFacet!]!) {
15
+ ...ClientProduct
16
+ product(locator: $locator) {
17
+ ...ProductDetailsFragment_product
18
+ }
19
+ }
20
+ `)
21
+
22
+ export interface BulkProductData {
23
+ sku: string
24
+ product?: ClientProductQueryQuery['product']
25
+ error?: Error
26
+ }
27
+
28
+ // Batch size to avoid overwhelming the server
29
+ const BATCH_SIZE = 10
30
+ const BATCH_DELAY_MS = 100
31
+
32
+ export const useBulkProductsQuery = (skus: string[]) => {
33
+ const { channel, locale } = useSession()
34
+ const [products, setProducts] = useState<BulkProductData[]>([])
35
+ const [isLoading, setIsLoading] = useState(false)
36
+ const [error, setError] = useState<Error | null>(null)
37
+
38
+ // Create a stable key for the SKUs array to use as a dependency
39
+ const skusKey = useMemo(() => {
40
+ return skus.join(',')
41
+ }, [skus])
42
+
43
+ useEffect(() => {
44
+ if (skus.length === 0) {
45
+ setProducts([])
46
+ setIsLoading(false)
47
+ return
48
+ }
49
+
50
+ const fetchProducts = async () => {
51
+ setIsLoading(true)
52
+ setError(null)
53
+
54
+ try {
55
+ if (!channel) {
56
+ throw new Error(
57
+ `useBulkProductsQuery: 'channel' from session is an empty string.`
58
+ )
59
+ }
60
+
61
+ const results: BulkProductData[] = []
62
+
63
+ for (let i = 0; i < skus.length; i += BATCH_SIZE) {
64
+ const batch = skus.slice(i, i + BATCH_SIZE)
65
+
66
+ const batchPromises = batch.map(
67
+ async (sku): Promise<BulkProductData> => {
68
+ try {
69
+ const variables: ClientProductQueryQueryVariables = {
70
+ locator: [
71
+ { key: 'id', value: sku },
72
+ { key: 'channel', value: channel },
73
+ { key: 'locale', value: locale },
74
+ ],
75
+ }
76
+
77
+ // Use POST method to avoid URL length issues with GET
78
+ const data = await request<
79
+ ClientProductQueryQuery,
80
+ ClientProductQueryQueryVariables
81
+ >(query, variables, {
82
+ fetchOptions: {
83
+ method: 'POST',
84
+ },
85
+ })
86
+
87
+ return {
88
+ sku,
89
+ product: data.product,
90
+ }
91
+ } catch (err) {
92
+ console.error(`Failed to fetch product ${sku}:`, err)
93
+ return {
94
+ sku,
95
+ error:
96
+ err instanceof Error
97
+ ? err
98
+ : new Error(`Failed to fetch product: ${sku}`),
99
+ }
100
+ }
101
+ }
102
+ )
103
+
104
+ const batchResults = await Promise.all(batchPromises)
105
+ results.push(...batchResults)
106
+
107
+ // Add a small delay between batches to avoid rate limiting
108
+ if (i + BATCH_SIZE < skus.length) {
109
+ await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY_MS))
110
+ }
111
+ }
112
+
113
+ setProducts(results)
114
+ } catch (err) {
115
+ setError(
116
+ err instanceof Error ? err : new Error('Failed to fetch products')
117
+ )
118
+ setProducts([])
119
+ } finally {
120
+ setIsLoading(false)
121
+ }
122
+ }
123
+
124
+ fetchProducts()
125
+ }, [skusKey, channel, locale, skus.length])
126
+
127
+ return { products, isLoading, error }
128
+ }
@@ -1,8 +1,8 @@
1
1
  import { useSearch } from '@faststore/sdk'
2
2
  import { gql } from '@generated'
3
3
  import type {
4
- ClientManyProductsQueryQuery,
5
- ClientManyProductsQueryQueryVariables,
4
+ ClientManyProductsQueryWithSearchIdQuery,
5
+ ClientManyProductsQueryWithSearchIdQueryVariables,
6
6
  } from '@generated/graphql'
7
7
  import deepEquals from 'fast-deep-equal'
8
8
  import {
@@ -34,7 +34,7 @@ export const useGalleryPage = (page: number) => {
34
34
  }
35
35
 
36
36
  export const query = gql(`
37
- query ClientManyProductsQuery(
37
+ query ClientManyProductsQueryWithSearchId(
38
38
  $first: Int!
39
39
  $after: String
40
40
  $sort: StoreSort!
@@ -61,6 +61,7 @@ export const query = gql(`
61
61
  }
62
62
  }
63
63
  }
64
+ searchId
64
65
  }
65
66
  }
66
67
  `)
@@ -68,8 +69,8 @@ export const query = gql(`
68
69
  const getKey = (object: any) => JSON.stringify(object)
69
70
 
70
71
  interface UseCreateUseGalleryPageProps {
71
- initialPages: ClientManyProductsQueryQuery
72
- serverManyProductsVariables: ClientManyProductsQueryQueryVariables
72
+ initialPages: ClientManyProductsQueryWithSearchIdQuery
73
+ serverManyProductsVariables: ClientManyProductsQueryWithSearchIdQueryVariables
73
74
  }
74
75
 
75
76
  /**
@@ -84,9 +85,10 @@ export const useCreateUseGalleryPage = (
84
85
  : []
85
86
 
86
87
  const [pages, setPages] =
87
- useState<ClientManyProductsQueryQuery[]>(initialPages)
88
+ useState<ClientManyProductsQueryWithSearchIdQuery[]>(initialPages)
88
89
  // We create pagesRef as a mirror of the pages state so we don't have to add pages as a dependency of the useGalleryPage hook
89
- const pagesRef = useRef<ClientManyProductsQueryQuery[]>(initialPages)
90
+ const pagesRef =
91
+ useRef<ClientManyProductsQueryWithSearchIdQuery[]>(initialPages)
90
92
  const pagesCache = useRef<string[]>(initialVariables)
91
93
 
92
94
  const useGalleryPage = useCallback(function useGalleryPage(page: number) {
@@ -116,8 +118,8 @@ export const useCreateUseGalleryPage = (
116
118
  const shouldFetch = !hasSameVariables || shouldFetchFirstPage
117
119
 
118
120
  const { data } = useQuery<
119
- ClientManyProductsQueryQuery,
120
- ClientManyProductsQueryQueryVariables
121
+ ClientManyProductsQueryWithSearchIdQuery,
122
+ ClientManyProductsQueryWithSearchIdQueryVariables
121
123
  >(query, localizedVariables, {
122
124
  fallbackData: null,
123
125
  suspense: true,
@@ -34,6 +34,7 @@ const query = gql(`
34
34
  metadata {
35
35
  ...SearchEvent_metadata
36
36
  }
37
+ searchId
37
38
  }
38
39
  }
39
40
  `)
@@ -11,4 +11,5 @@
11
11
  @import "src/components/sections/Section/section.scss";
12
12
 
13
13
  // Importing this component because is being used outside the context of the Section
14
- @import "@faststore/ui/src/components/molecules/Dropdown/styles.scss";
14
+ @import "@faststore/ui/src/components/organisms/QuickOrderDrawer/styles.scss";
15
+ @import "@faststore/ui/src/components/organisms/SlideOver/styles.scss";
@@ -1,59 +1,49 @@
1
- import discoveryConfig from 'discovery.config'
1
+ import { sessionStore } from 'src/sdk/session'
2
2
 
3
- export const STORAGE_KEY_AUTH_COOKIE_VALUE = 'faststore_auth_cookie_value'
3
+ export const STORAGE_KEY_PERSON_ID = 'faststore_person_id'
4
4
  export const STORAGE_KEY_CACHE_BUST_LAST_VALUE =
5
5
  'faststore_cache_bust_last_value'
6
6
 
7
7
  /**
8
- * Gets the VtexIdclientAutCookie value from browser
9
- * Note: vtex_segment is httpOnly and cannot be accessed via JavaScript,
10
- * so we only monitor VtexIdclientAutCookie_<account>
8
+ * Gets person?.id from session (via ValidateSession).
9
+ * Reads session store directly since auth cookies are httpOnly and inaccessible via JavaScript.
11
10
  */
12
- const getAuthCookieValue = (): string | null => {
13
- if (typeof document === 'undefined') {
11
+ const getPersonId = (): string | null => {
12
+ if (typeof window === 'undefined') {
14
13
  return null
15
14
  }
16
-
17
- const account = discoveryConfig.api.storeId
18
- const authCookieName = `VtexIdclientAutCookie_${account}`
19
- const cookies = document.cookie.split(';').map((cookie) => cookie.trim())
20
- const authCookie = cookies.find((c) => c.startsWith(`${authCookieName}=`))
21
-
22
- if (!authCookie) {
23
- return null
24
- }
25
-
26
- return authCookie.split('=').slice(1).join('=')
15
+ const session = sessionStore.read() ?? sessionStore.readInitial()
16
+ return session?.person?.id ?? null
27
17
  }
28
18
 
29
19
  /**
30
- * Gets the stored auth cookie value from sessionStorage (client-side only)
20
+ * Gets the stored person id from sessionStorage (client-side only)
31
21
  */
32
- const getStoredAuthCookieValue = (): string | null => {
22
+ const getStoredPersonId = (): string | null => {
33
23
  if (typeof sessionStorage === 'undefined') {
34
24
  return null
35
25
  }
36
26
 
37
27
  try {
38
- return sessionStorage.getItem(STORAGE_KEY_AUTH_COOKIE_VALUE)
28
+ return sessionStorage.getItem(STORAGE_KEY_PERSON_ID)
39
29
  } catch {
40
30
  return null
41
31
  }
42
32
  }
43
33
 
44
34
  /**
45
- * Stores the auth cookie value in sessionStorage (client-side only)
35
+ * Stores the person id in sessionStorage (client-side only)
46
36
  */
47
- const storeAuthCookieValue = (value: string | null): void => {
37
+ const storePersonId = (value: string | null): void => {
48
38
  if (typeof sessionStorage === 'undefined') {
49
39
  return
50
40
  }
51
41
 
52
42
  try {
53
43
  if (value === null) {
54
- sessionStorage.removeItem(STORAGE_KEY_AUTH_COOKIE_VALUE)
44
+ sessionStorage.removeItem(STORAGE_KEY_PERSON_ID)
55
45
  } else {
56
- sessionStorage.setItem(STORAGE_KEY_AUTH_COOKIE_VALUE, value)
46
+ sessionStorage.setItem(STORAGE_KEY_PERSON_ID, value)
57
47
  }
58
48
  } catch {
59
49
  // Ignore storage errors
@@ -93,13 +83,13 @@ const storeLastValue = (value: string): void => {
93
83
  /**
94
84
  * Clears all cache busting related data from sessionStorage (client-side only)
95
85
  */
96
- const clearStorage = (): void => {
86
+ const clearCacheBustingStorage = (): void => {
97
87
  if (typeof sessionStorage === 'undefined') {
98
88
  return
99
89
  }
100
90
 
101
91
  try {
102
- sessionStorage.removeItem(STORAGE_KEY_AUTH_COOKIE_VALUE)
92
+ sessionStorage.removeItem(STORAGE_KEY_PERSON_ID)
103
93
  sessionStorage.removeItem(STORAGE_KEY_CACHE_BUST_LAST_VALUE)
104
94
  } catch {
105
95
  // Ignore storage errors
@@ -107,28 +97,31 @@ const clearStorage = (): void => {
107
97
  }
108
98
 
109
99
  /**
110
- * Gets cache busting value for client-side based on auth cookie changes
100
+ * Gets cache busting value for client-side based on auth state changes.
101
+ * Uses person?.id from session (via useSession/ValidateSession) since auth cookies
102
+ * are now httpOnly and cannot be accessed via JavaScript.
111
103
  */
112
104
  export const getClientCacheBustingValue = (): string | null => {
113
- const currentAuthCookieValue = getAuthCookieValue()
105
+ const currentPersonId = getPersonId()
114
106
 
115
- // Guard clause: if auth cookie doesn't exist, clear storage and don't proceed with cache busting logic
116
- if (currentAuthCookieValue === null) {
117
- clearStorage()
107
+ // Guard clause: if user is not logged in (no person?.id), clear storage and don't proceed with cache busting logic
108
+ if (currentPersonId === null) {
109
+ clearCacheBustingStorage()
118
110
  return null
119
111
  }
120
112
 
121
- const storedAuthCookieValue = getStoredAuthCookieValue()
113
+ const storedPersonId = getStoredPersonId()
122
114
 
123
- // If auth cookie changed, update stored value and return new timestamp
124
- if (currentAuthCookieValue !== storedAuthCookieValue) {
125
- storeAuthCookieValue(currentAuthCookieValue)
115
+ // If person changed (login/logout or different user), update stored value and return new value
116
+ if (currentPersonId !== storedPersonId) {
117
+ storePersonId(currentPersonId)
126
118
  const timestamp = Date.now().toString()
127
- storeLastValue(timestamp)
128
- return timestamp
119
+ const value = `${timestamp}::${currentPersonId}`
120
+ storeLastValue(value)
121
+ return value
129
122
  }
130
123
 
131
- // Auth cookie hasn't changed, return last value or create one if it doesn't exist
124
+ // Person hasn't changed, return last value or create one if it doesn't exist
132
125
  const lastValue = getLastValue()
133
126
  if (lastValue) {
134
127
  return lastValue
@@ -136,6 +129,7 @@ export const getClientCacheBustingValue = (): string | null => {
136
129
 
137
130
  // Fallback: if no last value, create one
138
131
  const timestamp = Date.now().toString()
139
- storeLastValue(timestamp)
140
- return timestamp
132
+ const value = `${timestamp}::${currentPersonId}`
133
+ storeLastValue(value)
134
+ return value
141
135
  }