medusa-storefront-data 2.5.1 → 2.5.3

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 (293) hide show
  1. package/HOMEPAGE_CONFIG.md +83 -10
  2. package/package.json +160 -115
  3. package/src/server/cart.ts +1 -1
  4. package/src/server/dynamic-config.ts +132 -12
  5. package/src/server/help-faq-section-defaults.json +92 -0
  6. package/src/server/help-sections/help-faq.ts +25 -0
  7. package/src/server/help-sections/index.ts +8 -0
  8. package/src/server/homepage-config.types.ts +24 -0
  9. package/src/server/homepage-section-defaults.ts +3 -0
  10. package/src/server/normalize-homepage-config.ts +39 -0
  11. package/dist/segment-data/default-page-input.json +0 -191
  12. package/dist/src/config.d.ts +0 -3
  13. package/dist/src/config.d.ts.map +0 -1
  14. package/dist/src/config.js +0 -31
  15. package/dist/src/cookies.d.ts +0 -23
  16. package/dist/src/cookies.d.ts.map +0 -1
  17. package/dist/src/cookies.js +0 -140
  18. package/dist/src/dynamic-config-schema/index.d.ts +0 -103
  19. package/dist/src/dynamic-config-schema/index.d.ts.map +0 -1
  20. package/dist/src/dynamic-config-schema/index.js +0 -172
  21. package/dist/src/dynamic-config-schema/sections/about-brand.d.ts +0 -5
  22. package/dist/src/dynamic-config-schema/sections/about-brand.d.ts.map +0 -1
  23. package/dist/src/dynamic-config-schema/sections/about-brand.js +0 -30
  24. package/dist/src/dynamic-config-schema/sections/baptism-picks.d.ts +0 -5
  25. package/dist/src/dynamic-config-schema/sections/baptism-picks.d.ts.map +0 -1
  26. package/dist/src/dynamic-config-schema/sections/baptism-picks.js +0 -17
  27. package/dist/src/dynamic-config-schema/sections/baptism.d.ts +0 -5
  28. package/dist/src/dynamic-config-schema/sections/baptism.d.ts.map +0 -1
  29. package/dist/src/dynamic-config-schema/sections/baptism.js +0 -4
  30. package/dist/src/dynamic-config-schema/sections/blog-posts.d.ts +0 -5
  31. package/dist/src/dynamic-config-schema/sections/blog-posts.d.ts.map +0 -1
  32. package/dist/src/dynamic-config-schema/sections/blog-posts.js +0 -31
  33. package/dist/src/dynamic-config-schema/sections/brand-marquee.d.ts +0 -5
  34. package/dist/src/dynamic-config-schema/sections/brand-marquee.d.ts.map +0 -1
  35. package/dist/src/dynamic-config-schema/sections/brand-marquee.js +0 -9
  36. package/dist/src/dynamic-config-schema/sections/brand-pillars.d.ts +0 -5
  37. package/dist/src/dynamic-config-schema/sections/brand-pillars.d.ts.map +0 -1
  38. package/dist/src/dynamic-config-schema/sections/brand-pillars.js +0 -29
  39. package/dist/src/dynamic-config-schema/sections/category-pills.d.ts +0 -5
  40. package/dist/src/dynamic-config-schema/sections/category-pills.d.ts.map +0 -1
  41. package/dist/src/dynamic-config-schema/sections/category-pills.js +0 -4
  42. package/dist/src/dynamic-config-schema/sections/celebrity-trust.d.ts +0 -5
  43. package/dist/src/dynamic-config-schema/sections/celebrity-trust.d.ts.map +0 -1
  44. package/dist/src/dynamic-config-schema/sections/celebrity-trust.js +0 -4
  45. package/dist/src/dynamic-config-schema/sections/features.d.ts +0 -5
  46. package/dist/src/dynamic-config-schema/sections/features.d.ts.map +0 -1
  47. package/dist/src/dynamic-config-schema/sections/features.js +0 -12
  48. package/dist/src/dynamic-config-schema/sections/hero.d.ts +0 -6
  49. package/dist/src/dynamic-config-schema/sections/hero.d.ts.map +0 -1
  50. package/dist/src/dynamic-config-schema/sections/hero.js +0 -9
  51. package/dist/src/dynamic-config-schema/sections/index.d.ts +0 -24
  52. package/dist/src/dynamic-config-schema/sections/index.d.ts.map +0 -1
  53. package/dist/src/dynamic-config-schema/sections/index.js +0 -23
  54. package/dist/src/dynamic-config-schema/sections/instagram-posts.d.ts +0 -5
  55. package/dist/src/dynamic-config-schema/sections/instagram-posts.d.ts.map +0 -1
  56. package/dist/src/dynamic-config-schema/sections/instagram-posts.js +0 -30
  57. package/dist/src/dynamic-config-schema/sections/loved-by-moms.d.ts +0 -5
  58. package/dist/src/dynamic-config-schema/sections/loved-by-moms.d.ts.map +0 -1
  59. package/dist/src/dynamic-config-schema/sections/loved-by-moms.js +0 -4
  60. package/dist/src/dynamic-config-schema/sections/luxe-favourites.d.ts +0 -5
  61. package/dist/src/dynamic-config-schema/sections/luxe-favourites.d.ts.map +0 -1
  62. package/dist/src/dynamic-config-schema/sections/luxe-favourites.js +0 -4
  63. package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.d.ts +0 -5
  64. package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.d.ts.map +0 -1
  65. package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.js +0 -12
  66. package/dist/src/dynamic-config-schema/sections/new-arrivals.d.ts +0 -5
  67. package/dist/src/dynamic-config-schema/sections/new-arrivals.d.ts.map +0 -1
  68. package/dist/src/dynamic-config-schema/sections/new-arrivals.js +0 -12
  69. package/dist/src/dynamic-config-schema/sections/promo-announcements.d.ts +0 -5
  70. package/dist/src/dynamic-config-schema/sections/promo-announcements.d.ts.map +0 -1
  71. package/dist/src/dynamic-config-schema/sections/promo-announcements.js +0 -16
  72. package/dist/src/dynamic-config-schema/sections/promo-countdown.d.ts +0 -5
  73. package/dist/src/dynamic-config-schema/sections/promo-countdown.d.ts.map +0 -1
  74. package/dist/src/dynamic-config-schema/sections/promo-countdown.js +0 -16
  75. package/dist/src/dynamic-config-schema/sections/shop-by-age.d.ts +0 -5
  76. package/dist/src/dynamic-config-schema/sections/shop-by-age.d.ts.map +0 -1
  77. package/dist/src/dynamic-config-schema/sections/shop-by-age.js +0 -4
  78. package/dist/src/dynamic-config-schema/sections/shop-by-category.d.ts +0 -5
  79. package/dist/src/dynamic-config-schema/sections/shop-by-category.d.ts.map +0 -1
  80. package/dist/src/dynamic-config-schema/sections/shop-by-category.js +0 -4
  81. package/dist/src/dynamic-config-schema/sections/testimonials.d.ts +0 -5
  82. package/dist/src/dynamic-config-schema/sections/testimonials.d.ts.map +0 -1
  83. package/dist/src/dynamic-config-schema/sections/testimonials.js +0 -9
  84. package/dist/src/dynamic-config-schema/sections/theme-dresses.d.ts +0 -5
  85. package/dist/src/dynamic-config-schema/sections/theme-dresses.d.ts.map +0 -1
  86. package/dist/src/dynamic-config-schema/sections/theme-dresses.js +0 -4
  87. package/dist/src/dynamic-config-schema/sections/video-stories.d.ts +0 -5
  88. package/dist/src/dynamic-config-schema/sections/video-stories.d.ts.map +0 -1
  89. package/dist/src/dynamic-config-schema/sections/video-stories.js +0 -24
  90. package/dist/src/dynamic-config-schema/sections/why-choose-us.d.ts +0 -5
  91. package/dist/src/dynamic-config-schema/sections/why-choose-us.d.ts.map +0 -1
  92. package/dist/src/dynamic-config-schema/sections/why-choose-us.js +0 -9
  93. package/dist/src/dynamic-config-schema/shared.d.ts +0 -35
  94. package/dist/src/dynamic-config-schema/shared.d.ts.map +0 -1
  95. package/dist/src/dynamic-config-schema/shared.js +0 -99
  96. package/dist/src/dynamic-config-schema/site-configs.d.ts +0 -11
  97. package/dist/src/dynamic-config-schema/site-configs.d.ts.map +0 -1
  98. package/dist/src/dynamic-config-schema/site-configs.js +0 -70
  99. package/dist/src/edge.d.ts +0 -3
  100. package/dist/src/edge.d.ts.map +0 -1
  101. package/dist/src/edge.js +0 -1
  102. package/dist/src/middleware.d.ts +0 -3
  103. package/dist/src/middleware.d.ts.map +0 -1
  104. package/dist/src/middleware.js +0 -1
  105. package/dist/src/server/brand-pillars-from-categories.d.ts +0 -8
  106. package/dist/src/server/brand-pillars-from-categories.d.ts.map +0 -1
  107. package/dist/src/server/brand-pillars-from-categories.js +0 -92
  108. package/dist/src/server/cart.d.ts +0 -96
  109. package/dist/src/server/cart.d.ts.map +0 -1
  110. package/dist/src/server/cart.js +0 -797
  111. package/dist/src/server/categories.d.ts +0 -4
  112. package/dist/src/server/categories.d.ts.map +0 -1
  113. package/dist/src/server/categories.js +0 -34
  114. package/dist/src/server/collections.d.ts +0 -8
  115. package/dist/src/server/collections.d.ts.map +0 -1
  116. package/dist/src/server/collections.js +0 -39
  117. package/dist/src/server/config-merge.d.ts +0 -3
  118. package/dist/src/server/config-merge.d.ts.map +0 -1
  119. package/dist/src/server/config-merge.js +0 -31
  120. package/dist/src/server/contact.d.ts +0 -34
  121. package/dist/src/server/contact.d.ts.map +0 -1
  122. package/dist/src/server/contact.js +0 -57
  123. package/dist/src/server/customer-registration.d.ts +0 -142
  124. package/dist/src/server/customer-registration.d.ts.map +0 -1
  125. package/dist/src/server/customer-registration.js +0 -295
  126. package/dist/src/server/customer.d.ts +0 -48
  127. package/dist/src/server/customer.d.ts.map +0 -1
  128. package/dist/src/server/customer.js +0 -413
  129. package/dist/src/server/dynamic-config-api.d.ts +0 -11
  130. package/dist/src/server/dynamic-config-api.d.ts.map +0 -1
  131. package/dist/src/server/dynamic-config-api.js +0 -46
  132. package/dist/src/server/dynamic-config.d.ts +0 -157
  133. package/dist/src/server/dynamic-config.d.ts.map +0 -1
  134. package/dist/src/server/dynamic-config.js +0 -573
  135. package/dist/src/server/fulfillment.d.ts +0 -5
  136. package/dist/src/server/fulfillment.d.ts.map +0 -1
  137. package/dist/src/server/fulfillment.js +0 -47
  138. package/dist/src/server/guest.d.ts +0 -81
  139. package/dist/src/server/guest.d.ts.map +0 -1
  140. package/dist/src/server/guest.js +0 -183
  141. package/dist/src/server/home-sections/about-brand.d.ts +0 -9
  142. package/dist/src/server/home-sections/about-brand.d.ts.map +0 -1
  143. package/dist/src/server/home-sections/about-brand.js +0 -9
  144. package/dist/src/server/home-sections/baptism-picks.d.ts +0 -10
  145. package/dist/src/server/home-sections/baptism-picks.d.ts.map +0 -1
  146. package/dist/src/server/home-sections/baptism-picks.js +0 -27
  147. package/dist/src/server/home-sections/baptism.d.ts +0 -13
  148. package/dist/src/server/home-sections/baptism.d.ts.map +0 -1
  149. package/dist/src/server/home-sections/baptism.js +0 -43
  150. package/dist/src/server/home-sections/blog-posts.d.ts +0 -9
  151. package/dist/src/server/home-sections/blog-posts.d.ts.map +0 -1
  152. package/dist/src/server/home-sections/blog-posts.js +0 -9
  153. package/dist/src/server/home-sections/brand-marquee.d.ts +0 -8
  154. package/dist/src/server/home-sections/brand-marquee.d.ts.map +0 -1
  155. package/dist/src/server/home-sections/brand-marquee.js +0 -7
  156. package/dist/src/server/home-sections/brand-pillars.d.ts +0 -9
  157. package/dist/src/server/home-sections/brand-pillars.d.ts.map +0 -1
  158. package/dist/src/server/home-sections/brand-pillars.js +0 -9
  159. package/dist/src/server/home-sections/category-pills.d.ts +0 -9
  160. package/dist/src/server/home-sections/category-pills.d.ts.map +0 -1
  161. package/dist/src/server/home-sections/category-pills.js +0 -19
  162. package/dist/src/server/home-sections/celebrity-trust.d.ts +0 -12
  163. package/dist/src/server/home-sections/celebrity-trust.d.ts.map +0 -1
  164. package/dist/src/server/home-sections/celebrity-trust.js +0 -27
  165. package/dist/src/server/home-sections/features.d.ts +0 -9
  166. package/dist/src/server/home-sections/features.d.ts.map +0 -1
  167. package/dist/src/server/home-sections/features.js +0 -9
  168. package/dist/src/server/home-sections/hero.d.ts +0 -9
  169. package/dist/src/server/home-sections/hero.d.ts.map +0 -1
  170. package/dist/src/server/home-sections/hero.js +0 -9
  171. package/dist/src/server/home-sections/instagram-posts.d.ts +0 -9
  172. package/dist/src/server/home-sections/instagram-posts.d.ts.map +0 -1
  173. package/dist/src/server/home-sections/instagram-posts.js +0 -9
  174. package/dist/src/server/home-sections/loved-by-moms.d.ts +0 -12
  175. package/dist/src/server/home-sections/loved-by-moms.d.ts.map +0 -1
  176. package/dist/src/server/home-sections/loved-by-moms.js +0 -20
  177. package/dist/src/server/home-sections/luxe-favourites.d.ts +0 -11
  178. package/dist/src/server/home-sections/luxe-favourites.d.ts.map +0 -1
  179. package/dist/src/server/home-sections/luxe-favourites.js +0 -19
  180. package/dist/src/server/home-sections/new-arrivals-classic.d.ts +0 -8
  181. package/dist/src/server/home-sections/new-arrivals-classic.d.ts.map +0 -1
  182. package/dist/src/server/home-sections/new-arrivals-classic.js +0 -10
  183. package/dist/src/server/home-sections/new-arrivals.d.ts +0 -12
  184. package/dist/src/server/home-sections/new-arrivals.d.ts.map +0 -1
  185. package/dist/src/server/home-sections/new-arrivals.js +0 -28
  186. package/dist/src/server/home-sections/promo-announcements.d.ts +0 -7
  187. package/dist/src/server/home-sections/promo-announcements.d.ts.map +0 -1
  188. package/dist/src/server/home-sections/promo-announcements.js +0 -7
  189. package/dist/src/server/home-sections/promo-countdown.d.ts +0 -6
  190. package/dist/src/server/home-sections/promo-countdown.d.ts.map +0 -1
  191. package/dist/src/server/home-sections/promo-countdown.js +0 -5
  192. package/dist/src/server/home-sections/shared.d.ts +0 -10
  193. package/dist/src/server/home-sections/shared.d.ts.map +0 -1
  194. package/dist/src/server/home-sections/shared.js +0 -29
  195. package/dist/src/server/home-sections/shop-by-age.d.ts +0 -9
  196. package/dist/src/server/home-sections/shop-by-age.d.ts.map +0 -1
  197. package/dist/src/server/home-sections/shop-by-age.js +0 -17
  198. package/dist/src/server/home-sections/shop-by-category.d.ts +0 -10
  199. package/dist/src/server/home-sections/shop-by-category.d.ts.map +0 -1
  200. package/dist/src/server/home-sections/shop-by-category.js +0 -17
  201. package/dist/src/server/home-sections/testimonials.d.ts +0 -9
  202. package/dist/src/server/home-sections/testimonials.d.ts.map +0 -1
  203. package/dist/src/server/home-sections/testimonials.js +0 -9
  204. package/dist/src/server/home-sections/theme-dresses.d.ts +0 -12
  205. package/dist/src/server/home-sections/theme-dresses.d.ts.map +0 -1
  206. package/dist/src/server/home-sections/theme-dresses.js +0 -27
  207. package/dist/src/server/home-sections/video-stories.d.ts +0 -9
  208. package/dist/src/server/home-sections/video-stories.d.ts.map +0 -1
  209. package/dist/src/server/home-sections/video-stories.js +0 -9
  210. package/dist/src/server/home-sections/why-choose-us.d.ts +0 -9
  211. package/dist/src/server/home-sections/why-choose-us.d.ts.map +0 -1
  212. package/dist/src/server/home-sections/why-choose-us.js +0 -9
  213. package/dist/src/server/home.d.ts +0 -51
  214. package/dist/src/server/home.d.ts.map +0 -1
  215. package/dist/src/server/home.js +0 -1
  216. package/dist/src/server/homepage-config.types.d.ts +0 -274
  217. package/dist/src/server/homepage-config.types.d.ts.map +0 -1
  218. package/dist/src/server/homepage-config.types.js +0 -33
  219. package/dist/src/server/homepage-section-defaults.d.ts +0 -188
  220. package/dist/src/server/homepage-section-defaults.d.ts.map +0 -1
  221. package/dist/src/server/homepage-section-defaults.js +0 -188
  222. package/dist/src/server/index.d.ts +0 -25
  223. package/dist/src/server/index.d.ts.map +0 -1
  224. package/dist/src/server/index.js +0 -24
  225. package/dist/src/server/locale-actions.d.ts +0 -14
  226. package/dist/src/server/locale-actions.d.ts.map +0 -1
  227. package/dist/src/server/locale-actions.js +0 -58
  228. package/dist/src/server/locales.d.ts +0 -8
  229. package/dist/src/server/locales.d.ts.map +0 -1
  230. package/dist/src/server/locales.js +0 -12
  231. package/dist/src/server/normalize-homepage-config.d.ts +0 -7
  232. package/dist/src/server/normalize-homepage-config.d.ts.map +0 -1
  233. package/dist/src/server/normalize-homepage-config.js +0 -213
  234. package/dist/src/server/notifications.d.ts +0 -2
  235. package/dist/src/server/notifications.d.ts.map +0 -1
  236. package/dist/src/server/notifications.js +0 -20
  237. package/dist/src/server/onboarding.d.ts +0 -2
  238. package/dist/src/server/onboarding.d.ts.map +0 -1
  239. package/dist/src/server/onboarding.js +0 -8
  240. package/dist/src/server/orders.d.ts +0 -63
  241. package/dist/src/server/orders.d.ts.map +0 -1
  242. package/dist/src/server/orders.js +0 -230
  243. package/dist/src/server/page-input.d.ts +0 -19
  244. package/dist/src/server/page-input.d.ts.map +0 -1
  245. package/dist/src/server/page-input.js +0 -42
  246. package/dist/src/server/payment-details.d.ts +0 -5
  247. package/dist/src/server/payment-details.d.ts.map +0 -1
  248. package/dist/src/server/payment-details.js +0 -28
  249. package/dist/src/server/payment.d.ts +0 -3
  250. package/dist/src/server/payment.d.ts.map +0 -1
  251. package/dist/src/server/payment.js +0 -13
  252. package/dist/src/server/pincode.d.ts +0 -7
  253. package/dist/src/server/pincode.d.ts.map +0 -1
  254. package/dist/src/server/pincode.js +0 -30
  255. package/dist/src/server/products.d.ts +0 -54
  256. package/dist/src/server/products.d.ts.map +0 -1
  257. package/dist/src/server/products.js +0 -154
  258. package/dist/src/server/regions.d.ts +0 -5
  259. package/dist/src/server/regions.d.ts.map +0 -1
  260. package/dist/src/server/regions.js +0 -57
  261. package/dist/src/server/resolve-home-segment-data.d.ts +0 -25
  262. package/dist/src/server/resolve-home-segment-data.d.ts.map +0 -1
  263. package/dist/src/server/resolve-home-segment-data.js +0 -20
  264. package/dist/src/server/returns.d.ts +0 -29
  265. package/dist/src/server/returns.d.ts.map +0 -1
  266. package/dist/src/server/returns.js +0 -132
  267. package/dist/src/server/shoppable-looks.d.ts +0 -17
  268. package/dist/src/server/shoppable-looks.d.ts.map +0 -1
  269. package/dist/src/server/shoppable-looks.js +0 -136
  270. package/dist/src/server/swaps.d.ts +0 -15
  271. package/dist/src/server/swaps.d.ts.map +0 -1
  272. package/dist/src/server/swaps.js +0 -89
  273. package/dist/src/server/variants.d.ts +0 -3
  274. package/dist/src/server/variants.d.ts.map +0 -1
  275. package/dist/src/server/variants.js +0 -15
  276. package/dist/src/server/wishlist.d.ts +0 -11
  277. package/dist/src/server/wishlist.d.ts.map +0 -1
  278. package/dist/src/server/wishlist.js +0 -49
  279. package/dist/src/util/get-locale-header.d.ts +0 -4
  280. package/dist/src/util/get-locale-header.d.ts.map +0 -1
  281. package/dist/src/util/get-locale-header.js +0 -7
  282. package/dist/src/util/medusa-error.d.ts +0 -2
  283. package/dist/src/util/medusa-error.d.ts.map +0 -1
  284. package/dist/src/util/medusa-error.js +0 -18
  285. package/dist/src/util/revalidate-cart.d.ts +0 -2
  286. package/dist/src/util/revalidate-cart.d.ts.map +0 -1
  287. package/dist/src/util/revalidate-cart.js +0 -8
  288. package/dist/src/util/sort-products.d.ts +0 -3
  289. package/dist/src/util/sort-products.d.ts.map +0 -1
  290. package/dist/src/util/sort-products.js +0 -1
  291. package/dist/src/util/store-client.d.ts +0 -11
  292. package/dist/src/util/store-client.d.ts.map +0 -1
  293. package/dist/src/util/store-client.js +0 -75
@@ -1,797 +0,0 @@
1
- "use server";
2
- import { sdk } from "../config";
3
- import medusaError from "../util/medusa-error";
4
- import { revalidateTag, revalidatePath } from "next/cache";
5
- import { redirect } from "next/navigation";
6
- import { headers as nextHeaders } from "next/headers";
7
- import { getAuthHeaders, getCacheOptions, getCacheTag, getCartId, removeCartId, setCartId, getHoldCartId, setBuyNowCartId, removeBuyNowCartId, } from "../cookies";
8
- import { getRegion } from "./regions";
9
- function normalizeCartEmail(email) {
10
- if (typeof email !== "string")
11
- return undefined;
12
- const normalized = email.trim().toLowerCase();
13
- return normalized || undefined;
14
- }
15
- function isValidCartEmail(email) {
16
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
17
- }
18
- import { getLocale } from "./locale-actions";
19
- import { retrieveCustomer } from "./customer";
20
- import { medusaCartCreate, medusaCartRetrieve, medusaCartUpdate, medusaCartAddLineItem, medusaCartUpdateLineItem, medusaCartRemoveLineItem, medusaCartApplyPromotions, medusaCartAddShippingMethod, medusaCartComplete, medusaCartSkipMerge, medusaCartDelete, medusaCartList, medusaShippingOptionsList, MEDUSA_STORE_CART_DETAIL_FIELDS, } from "medusa-services/cart";
21
- import { medusaCustomerCreateAddress, medusaCustomerRetrieve, medusaCustomerUpdateAddress, } from "medusa-services/customer";
22
- import { medusaPaymentSessionInitiate } from "medusa-services/payment";
23
- import { getStoreClientOptions } from "../util/store-client";
24
- import { revalidateCartTags } from "../util/revalidate-cart";
25
- import { cache } from "react";
26
- function throwCartError(error) {
27
- if (error && typeof error === "object" && "response" in error) {
28
- medusaError(error);
29
- }
30
- throw error instanceof Error ? error : new Error(String(error));
31
- }
32
- /**
33
- * Retrieves a cart by its ID. If no ID is provided, it will use the cart ID from the cookies.
34
- * @param cartId - optional - The ID of the cart to retrieve.
35
- * @returns The cart object if found, or null if not found.
36
- */
37
- export const retrieveCart = cache(async (cartId, fields) => {
38
- let id = cartId || (await getCartId());
39
- const heldId = await getHoldCartId();
40
- // AUTO-RESTORE LOGIC:
41
- // If we're not explicitly asking for a specific cartId and we have an active cart
42
- if (!cartId && id) {
43
- try {
44
- const headerList = await nextHeaders();
45
- const pathname = headerList.get("x-pathname") || headerList.get("referer") || "";
46
- // Skip metadata check if we are clearly in checkout to avoid extra API call
47
- if (!pathname.includes("/checkout")) {
48
- const options = await getStoreClientOptions();
49
- const currentCart = await medusaCartRetrieve(id, options, { fields: "metadata" })
50
- .then(({ cart }) => cart)
51
- .catch(() => null);
52
- const cartMeta = currentCart?.metadata;
53
- if (cartMeta?.is_buy_now || cartMeta?.is_reorder) {
54
- await removeBuyNowCartId();
55
- id = await getCartId(); // Re-fetch ID which will now fall back to the real main cart
56
- revalidateTag("carts");
57
- }
58
- }
59
- }
60
- catch (e) {
61
- // Silent fail
62
- }
63
- }
64
- fields ??= MEDUSA_STORE_CART_DETAIL_FIELDS;
65
- if (!id) {
66
- return null;
67
- }
68
- const authHeaders = {
69
- ...(await getAuthHeaders()),
70
- };
71
- const next = {
72
- ...(await getCacheOptions("carts")),
73
- };
74
- return await sdk.client
75
- .fetch(`/store/carts/${id}`, {
76
- method: "GET",
77
- query: {
78
- fields,
79
- },
80
- headers: authHeaders,
81
- next,
82
- cache: "no-store",
83
- })
84
- .then(({ cart }) => {
85
- return cart;
86
- })
87
- .catch(() => null);
88
- });
89
- export async function getOrSetCart(countryCode) {
90
- const region = await getRegion(countryCode);
91
- if (!region) {
92
- throw new Error(`Region not found for country code: ${countryCode}`);
93
- }
94
- let cart = await retrieveCart(undefined, "id,region_id");
95
- const options = await getStoreClientOptions();
96
- if (!cart) {
97
- const locale = await getLocale();
98
- const { cart: createdCart } = await medusaCartCreate(options, {
99
- region_id: region.id,
100
- locale: locale || undefined,
101
- });
102
- cart = createdCart;
103
- await setCartId(cart.id);
104
- const cartCacheTag = await getCacheTag("carts");
105
- revalidateTag(cartCacheTag);
106
- }
107
- if (cart && cart?.region_id !== region.id) {
108
- await medusaCartUpdate(cart.id, { region_id: region.id }, options);
109
- const cartCacheTag = await getCacheTag("carts");
110
- revalidateTag(cartCacheTag);
111
- }
112
- return cart;
113
- }
114
- export async function updateCart(data) {
115
- const cartId = await getCartId();
116
- if (!cartId) {
117
- throw new Error("No existing cart found, please create one before updating");
118
- }
119
- try {
120
- const options = await getStoreClientOptions();
121
- const { cart } = await medusaCartUpdate(cartId, data, options);
122
- await revalidateCartTags();
123
- return cart;
124
- }
125
- catch (e) {
126
- throwCartError(e);
127
- }
128
- }
129
- export async function addToCart({ variantId, quantity, countryCode, }) {
130
- if (!variantId) {
131
- throw new Error("Missing variant ID when adding to cart");
132
- }
133
- const cart = await getOrSetCart(countryCode);
134
- if (!cart) {
135
- throw new Error("Error retrieving or creating cart");
136
- }
137
- try {
138
- const options = await getStoreClientOptions();
139
- await medusaCartAddLineItem(cart.id, { variant_id: variantId, quantity }, options);
140
- await revalidateCartTags();
141
- }
142
- catch (e) {
143
- throwCartError(e);
144
- }
145
- }
146
- export async function buyNow({ variantId, quantity, countryCode, }) {
147
- if (!variantId) {
148
- throw new Error("Missing variant ID when adding to cart");
149
- }
150
- const region = await getRegion(countryCode);
151
- if (!region) {
152
- throw new Error(`Region not found for country code: ${countryCode}`);
153
- }
154
- const options = await getStoreClientOptions();
155
- const locale = await getLocale();
156
- // 1. Create a NEW cart regardless of existing one
157
- const { cart } = await medusaCartCreate(options, {
158
- region_id: region.id,
159
- locale: locale || undefined,
160
- metadata: { is_buy_now: true },
161
- });
162
- // Save the new cart id in "buy_now_cart_id" cookie
163
- await removeBuyNowCartId();
164
- await setBuyNowCartId(cart.id);
165
- // Ensure this new cart is not merged with existing ones
166
- try {
167
- await medusaCartSkipMerge(cart.id, options);
168
- }
169
- catch (e) {
170
- console.error("Failed to skip cart merge for buy now cart:", e);
171
- }
172
- // 2. Add the item to this new cart
173
- await medusaCartAddLineItem(cart.id, { variant_id: variantId, quantity }, options);
174
- // 3. (REMOVED: No longer overwriting the main cart ID, because getCartId handles buy_now_cart_id priority)
175
- // 4. OPTIMIZATION: If user is logged in and has addresses, auto-fill and skip to payment
176
- const customer = await retrieveCustomer().catch(() => null);
177
- const defaultAddress = customer?.addresses?.find(a => a.is_default_shipping || a.metadata?.is_default === "true" || a.metadata?.is_default === true) || customer?.addresses?.[0];
178
- let skipToPayment = false;
179
- if (defaultAddress) {
180
- try {
181
- // Set addresses
182
- await medusaCartUpdate(cart.id, {
183
- shipping_address: {
184
- first_name: defaultAddress.first_name,
185
- last_name: defaultAddress.last_name,
186
- address_1: defaultAddress.address_1,
187
- address_2: defaultAddress.address_2,
188
- city: defaultAddress.city,
189
- country_code: defaultAddress.country_code,
190
- postal_code: defaultAddress.postal_code,
191
- province: defaultAddress.province,
192
- phone: defaultAddress.phone,
193
- company: defaultAddress.company,
194
- },
195
- billing_address: {
196
- first_name: defaultAddress.first_name,
197
- last_name: defaultAddress.last_name,
198
- address_1: defaultAddress.address_1,
199
- address_2: defaultAddress.address_2,
200
- city: defaultAddress.city,
201
- country_code: defaultAddress.country_code,
202
- postal_code: defaultAddress.postal_code,
203
- province: defaultAddress.province,
204
- phone: defaultAddress.phone,
205
- company: defaultAddress.company,
206
- },
207
- email: customer?.email ?? "",
208
- }, options);
209
- // Fetch and set first shipping method
210
- const { shipping_options } = await medusaShippingOptionsList(cart.id, options);
211
- if (shipping_options?.length > 0) {
212
- await medusaCartAddShippingMethod(cart.id, shipping_options[0].id, options);
213
- skipToPayment = true;
214
- }
215
- }
216
- catch (e) {
217
- // Fallback to normal checkout if anything fails
218
- console.error("Failed to auto-fill address and shipping:", e);
219
- }
220
- }
221
- const cartCacheTag = await getCacheTag("carts");
222
- revalidateTag(cartCacheTag);
223
- revalidatePath(`/${countryCode}/checkout`, "page");
224
- // 5. Redirect to checkout (default or skipped to payment)
225
- if (skipToPayment) {
226
- redirect(`/${countryCode}/checkout?step=payment&cart_id=${cart.id}`);
227
- }
228
- else {
229
- redirect(`/${countryCode}/checkout?cart_id=${cart.id}`);
230
- }
231
- }
232
- export async function updateLineItem({ lineId, quantity, }) {
233
- if (!lineId) {
234
- throw new Error("Missing lineItem ID when updating line item");
235
- }
236
- const cartId = await getCartId();
237
- if (!cartId) {
238
- throw new Error("Missing cart ID when updating line item");
239
- }
240
- try {
241
- const options = await getStoreClientOptions();
242
- await medusaCartUpdateLineItem(cartId, lineId, { quantity }, options);
243
- await revalidateCartTags();
244
- }
245
- catch (e) {
246
- throwCartError(e);
247
- }
248
- }
249
- export async function deleteLineItem(lineId) {
250
- if (!lineId) {
251
- throw new Error("Missing lineItem ID when deleting line item");
252
- }
253
- const cartId = await getCartId();
254
- if (!cartId) {
255
- throw new Error("Missing cart ID when deleting line item");
256
- }
257
- try {
258
- const options = await getStoreClientOptions();
259
- await medusaCartRemoveLineItem(cartId, lineId, options);
260
- await revalidateCartTags();
261
- }
262
- catch (e) {
263
- throwCartError(e);
264
- }
265
- }
266
- export async function updateLineItemVariant({ lineId, variantId, quantity, countryCode, }) {
267
- if (!lineId) {
268
- throw new Error("Missing lineItem ID when updating variant");
269
- }
270
- if (!variantId) {
271
- throw new Error("Missing variant ID when updating variant");
272
- }
273
- // Delete the old line item
274
- await deleteLineItem(lineId);
275
- // Add new line item with the new variant
276
- await addToCart({
277
- variantId,
278
- quantity,
279
- countryCode,
280
- });
281
- }
282
- export async function setShippingMethod({ cartId, shippingMethodId, }) {
283
- try {
284
- const options = await getStoreClientOptions();
285
- await medusaCartAddShippingMethod(cartId, shippingMethodId, options);
286
- const cartCacheTag = await getCacheTag("carts");
287
- revalidateTag(cartCacheTag);
288
- }
289
- catch (e) {
290
- throwCartError(e);
291
- }
292
- }
293
- /**
294
- * Sets a shipping method silently without triggering a full page revalidation.
295
- */
296
- export async function setShippingMethodSilently({ cartId, shippingMethodId, }) {
297
- try {
298
- const options = await getStoreClientOptions();
299
- await medusaCartAddShippingMethod(cartId, shippingMethodId, options);
300
- return { success: true };
301
- }
302
- catch (e) {
303
- return { success: false };
304
- }
305
- }
306
- export async function initiatePaymentSession(cart, data) {
307
- // 1. RE-FETCH cart with NO CACHE to ensure we have the latest data from the DB
308
- const latestCart = await retrieveCart(cart.id);
309
- if (!latestCart)
310
- throw new Error("Cart not found");
311
- // Helper to normalize phone numbers for Razorpay (requires +91 for India if 10 digits)
312
- const normalize = (p) => {
313
- if (!p)
314
- return undefined;
315
- const cleaned = String(p).replace(/\D/g, "");
316
- // India specific optimization (+91)
317
- if (cleaned.length === 10)
318
- return `+91${cleaned}`;
319
- if (cleaned.length > 10 && !String(p).startsWith("+"))
320
- return `+${cleaned}`;
321
- return p;
322
- };
323
- const rawPhone = latestCart.shipping_address?.phone || latestCart.billing_address?.phone;
324
- const phone = normalize(rawPhone);
325
- // 2. Critical Fix for Razorpay: Ensure normalized phone is in BOTH shipping and billing addresses
326
- if (phone) {
327
- const addressUpdates = {};
328
- // Clean address helper to ensure we pass a clean object to the update API
329
- const cleanAddress = (addr) => {
330
- if (!addr)
331
- return null;
332
- return {
333
- first_name: addr.first_name,
334
- last_name: addr.last_name,
335
- address_1: addr.address_1,
336
- address_2: addr.address_2 || "",
337
- city: addr.city,
338
- country_code: addr.country_code,
339
- postal_code: addr.postal_code,
340
- province: addr.province,
341
- company: addr.company,
342
- phone: phone
343
- };
344
- };
345
- // Update if phone is missing in DB
346
- if (latestCart.shipping_address && !latestCart.shipping_address.phone) {
347
- addressUpdates.shipping_address = cleanAddress(latestCart.shipping_address);
348
- }
349
- if (latestCart.billing_address && !latestCart.billing_address.phone) {
350
- addressUpdates.billing_address = cleanAddress(latestCart.billing_address) || cleanAddress(latestCart.shipping_address);
351
- }
352
- if (Object.keys(addressUpdates).length > 0) {
353
- const options = await getStoreClientOptions();
354
- await medusaCartUpdate(latestCart.id, addressUpdates, options);
355
- }
356
- }
357
- // 3. Final re-fetch (direct call to bypass any lib-level cache)
358
- const options = await getStoreClientOptions();
359
- const { cart: finalCartRaw } = await medusaCartRetrieve(cart.id, options, {
360
- fields: "*shipping_address,*billing_address",
361
- });
362
- const finalCart = finalCartRaw;
363
- // 4. PRE-FLIGHT VALIDATION: Only strictly block for Razorpay, be more lenient for COD
364
- const isRazorpayProvider = data.provider_id.includes("razorpay");
365
- const displayPhone = finalCart.shipping_address?.phone || finalCart.billing_address?.phone || phone;
366
- if (isRazorpayProvider && !displayPhone) {
367
- throw new Error(`CRITICAL Error: Phone number is missing from your address. Razorpay requires a contact number for verification. Please enter your phone number.`);
368
- }
369
- if (isRazorpayProvider && !finalCart.email) {
370
- throw new Error(`CRITICAL Error: Email is missing from your cart. Razorpay requires an email address. Please enter your email.`);
371
- }
372
- // 5. ENHANCED DATA FOR RAZORPAY:
373
- const enhancedData = {
374
- ...data,
375
- data: {
376
- ...(data.data || {}),
377
- billing_address: finalCart.billing_address || finalCart.shipping_address,
378
- customer: {
379
- email: finalCart.email,
380
- phone: displayPhone,
381
- first_name: finalCart.billing_address?.first_name || finalCart.shipping_address?.first_name,
382
- last_name: finalCart.billing_address?.last_name || finalCart.shipping_address?.last_name,
383
- }
384
- }
385
- };
386
- try {
387
- await medusaPaymentSessionInitiate(finalCart.id, enhancedData, options);
388
- const { cart: refreshedCart } = await medusaCartRetrieve(finalCart.id, options, {
389
- fields: `${MEDUSA_STORE_CART_DETAIL_FIELDS}, *payment_collection, *payment_collection.payment_sessions`,
390
- });
391
- const cartCacheTag = await getCacheTag("carts");
392
- revalidateTag(cartCacheTag);
393
- return refreshedCart;
394
- }
395
- catch (e) {
396
- const errorMsg = e.message || e.response?.data?.message || "Unknown error";
397
- const label = isRazorpayProvider ? "Razorpay" : "Payment";
398
- throw new Error(`${label} initialization failed: ${errorMsg}`);
399
- }
400
- }
401
- export async function applyPromotions(codes) {
402
- const cartId = await getCartId();
403
- if (!cartId) {
404
- throw new Error("No existing cart found");
405
- }
406
- try {
407
- const options = await getStoreClientOptions();
408
- const { cart } = await medusaCartApplyPromotions(cartId, codes, options);
409
- await revalidateCartTags();
410
- return cart;
411
- }
412
- catch (e) {
413
- throwCartError(e);
414
- }
415
- }
416
- export async function applyGiftCard(code) {
417
- // const cartId = getCartId()
418
- // if (!cartId) return "No cartId cookie found"
419
- // try {
420
- // await updateCart(cartId, { gift_cards: [{ code }] }).then(() => {
421
- // revalidateTag("cart")
422
- // })
423
- // } catch (error: any) {
424
- // throw error
425
- // }
426
- }
427
- export async function removeDiscount(code) {
428
- // const cartId = getCartId()
429
- // if (!cartId) return "No cartId cookie found"
430
- // try {
431
- // await deleteDiscount(cartId, code)
432
- // revalidateTag("cart")
433
- // } catch (error: any) {
434
- // throw error
435
- // }
436
- }
437
- export async function removeGiftCard(codeToRemove, giftCards
438
- // giftCards: GiftCard[]
439
- ) {
440
- // const cartId = getCartId()
441
- // if (!cartId) return "No cartId cookie found"
442
- // try {
443
- // await updateCart(cartId, {
444
- // gift_cards: [...giftCards]
445
- // .filter((gc) => gc.code !== codeToRemove)
446
- // .map((gc) => ({ code: gc.code })),
447
- // }).then(() => {
448
- // revalidateTag("cart")
449
- // })
450
- // } catch (error: any) {
451
- // throw error
452
- // }
453
- }
454
- export async function submitPromotionForm(currentState, formData) {
455
- const code = formData.get("code");
456
- try {
457
- await applyPromotions([code]);
458
- }
459
- catch (e) {
460
- return e.message;
461
- }
462
- }
463
- // TODO: Pass a POJO instead of a form entity here
464
- export async function setAddresses(currentState, formData) {
465
- try {
466
- if (!formData) {
467
- throw new Error("No form data found when setting addresses");
468
- }
469
- const cartId = await getCartId();
470
- if (!cartId) {
471
- throw new Error("No existing cart found when setting addresses");
472
- }
473
- const shippingCountryCode = formData.get("shipping_address.country_code")?.toLowerCase() || "in";
474
- const normalize = (p) => {
475
- if (!p)
476
- return undefined;
477
- const cleaned = String(p).replace(/\D/g, "");
478
- if (cleaned.length === 10)
479
- return `+91${cleaned}`;
480
- if (cleaned.length > 10 && !String(p).startsWith("+"))
481
- return `+${cleaned}`;
482
- return String(p);
483
- };
484
- const rawPhone = formData.get("shipping_address.phone");
485
- const phone = normalize(rawPhone);
486
- const shippingAddress = {
487
- first_name: formData.get("shipping_address.first_name"),
488
- last_name: formData.get("shipping_address.last_name"),
489
- address_1: formData.get("shipping_address.address_1"),
490
- address_2: formData.get("shipping_address.address_2") || "",
491
- company: formData.get("shipping_address.company"),
492
- postal_code: formData.get("shipping_address.postal_code"),
493
- city: formData.get("shipping_address.city"),
494
- country_code: shippingCountryCode,
495
- province: formData.get("shipping_address.province"),
496
- phone: phone,
497
- };
498
- const data = {
499
- shipping_address: shippingAddress,
500
- email: normalizeCartEmail(formData.get("email")),
501
- };
502
- if (data.email && !isValidCartEmail(data.email)) {
503
- throw new Error("Please enter a valid email address.");
504
- }
505
- // Save address to customer profile if logged in
506
- const authHeaders = await getAuthHeaders();
507
- if (authHeaders && "authorization" in authHeaders) {
508
- try {
509
- const options = await getStoreClientOptions();
510
- const { customer } = await medusaCustomerRetrieve(options, { fields: "*addresses" });
511
- const addressExists = customer?.addresses?.some((a) => a.address_1 === shippingAddress.address_1 &&
512
- a.postal_code === shippingAddress.postal_code &&
513
- a.city === shippingAddress.city &&
514
- a.first_name === shippingAddress.first_name &&
515
- a.last_name === shippingAddress.last_name);
516
- if (!addressExists) {
517
- await medusaCustomerCreateAddress(shippingAddress, options);
518
- const customerCacheTag = await getCacheTag("customers");
519
- revalidateTag(customerCacheTag);
520
- }
521
- }
522
- catch (e) {
523
- // Silently fail when saving address to customer profile
524
- }
525
- }
526
- const sameAsBilling = formData.get("same_as_billing");
527
- if (sameAsBilling === "on") {
528
- data.billing_address = { ...data.shipping_address };
529
- }
530
- if (sameAsBilling !== "on") {
531
- const bPhone = normalize(formData.get("billing_address.phone")) || phone;
532
- data.billing_address = {
533
- first_name: formData.get("billing_address.first_name"),
534
- last_name: formData.get("billing_address.last_name"),
535
- address_1: formData.get("billing_address.address_1"),
536
- address_2: formData.get("billing_address.address_2") || "",
537
- company: formData.get("billing_address.company"),
538
- postal_code: formData.get("billing_address.postal_code"),
539
- city: formData.get("billing_address.city"),
540
- country_code: shippingCountryCode,
541
- province: formData.get("billing_address.province"),
542
- phone: bPhone,
543
- };
544
- }
545
- await updateCart(data);
546
- }
547
- catch (e) {
548
- return e.message;
549
- }
550
- revalidateTag("carts");
551
- }
552
- /**
553
- * Places an order for a cart. If no cart ID is provided, it will use the cart ID from the cookies.
554
- * @param cartId - optional - The ID of the cart to place an order for.
555
- * @returns The cart object if the order was successful, or null if not.
556
- */
557
- export async function placeOrder(cartId) {
558
- const id = cartId || (await getCartId());
559
- if (!id) {
560
- throw new Error("No existing cart found when placing an order");
561
- }
562
- let cartRes;
563
- try {
564
- const options = await getStoreClientOptions();
565
- cartRes = await medusaCartComplete(id, options);
566
- const cartCacheTag = await getCacheTag("carts");
567
- revalidateTag(cartCacheTag);
568
- }
569
- catch (e) {
570
- throwCartError(e);
571
- }
572
- if (cartRes?.type === "order") {
573
- const order = cartRes.order;
574
- const countryCode = order.shipping_address?.country_code?.toLowerCase();
575
- const orderCacheTag = await getCacheTag("orders");
576
- revalidateTag(orderCacheTag);
577
- // NEW LOGIC: Check if we just completed a Buy Now cart
578
- const { cookies: nextCookies } = await import("next/headers");
579
- const cookiesStore = await nextCookies();
580
- const buyNowId = cookiesStore.get("buy_now_cart_id")?.value;
581
- if (buyNowId) {
582
- // If a Buy Now cart was completed, remove its cookie ONLY.
583
- // Do NOT touch _medusa_cart_id, so the main cart is preserved!
584
- await removeBuyNowCartId();
585
- }
586
- else {
587
- // Regular checkout: clear the main cart
588
- await removeCartId();
589
- }
590
- redirect(`/${countryCode}/order/${order.id}/confirmed`);
591
- }
592
- return cartRes.cart;
593
- }
594
- /**
595
- * Updates the countrycode param and revalidates the regions cache
596
- * @param regionId
597
- * @param countryCode
598
- */
599
- export async function updateRegion(countryCode, currentPath) {
600
- const cartId = await getCartId();
601
- const region = await getRegion(countryCode);
602
- if (!region) {
603
- throw new Error(`Region not found for country code: ${countryCode}`);
604
- }
605
- if (cartId) {
606
- await updateCart({ region_id: region.id });
607
- const cartCacheTag = await getCacheTag("carts");
608
- revalidateTag(cartCacheTag);
609
- }
610
- const regionCacheTag = await getCacheTag("regions");
611
- revalidateTag(regionCacheTag);
612
- const productsCacheTag = await getCacheTag("products");
613
- revalidateTag(productsCacheTag);
614
- redirect(`/${countryCode}${currentPath}`);
615
- }
616
- export async function listCartOptions() {
617
- const cartId = await getCartId();
618
- const headers = {
619
- ...(await getAuthHeaders()),
620
- };
621
- const next = {
622
- ...(await getCacheOptions("shippingOptions")),
623
- };
624
- return await sdk.client.fetch("/store/shipping-options", {
625
- query: { cart_id: cartId },
626
- next,
627
- headers,
628
- cache: "force-cache",
629
- });
630
- }
631
- export async function addCustomerAddressToCart(currentState, formData) {
632
- try {
633
- const shippingCountryCode = formData.get("shipping_address.country_code")?.toLowerCase() || "in";
634
- // Parse address data from formData (which uses shipping_address. prefix)
635
- const addressData = {
636
- first_name: formData.get("shipping_address.first_name"),
637
- last_name: formData.get("shipping_address.last_name"),
638
- company: formData.get("shipping_address.company"),
639
- address_1: formData.get("shipping_address.address_1"),
640
- address_2: formData.get("shipping_address.address_2"),
641
- city: formData.get("shipping_address.city"),
642
- postal_code: formData.get("shipping_address.postal_code"),
643
- province: formData.get("shipping_address.province"),
644
- country_code: shippingCountryCode,
645
- phone: formData.get("shipping_address.phone"),
646
- metadata: {
647
- is_default: formData.get("is_default") === "true",
648
- address_type: formData.get("address_type"),
649
- },
650
- };
651
- const addressId = formData.get("address_id");
652
- // 1. Add/Update Customer Address Book
653
- // We try/catch this separately so if it fails (e.g. user not logged in), we still try to proceed with checkout
654
- try {
655
- const options = await getStoreClientOptions();
656
- if (addressId) {
657
- await medusaCustomerUpdateAddress(addressId, addressData, options);
658
- }
659
- else {
660
- await medusaCustomerCreateAddress(addressData, options);
661
- }
662
- const customerCacheTag = await getCacheTag("customers");
663
- revalidateTag(customerCacheTag);
664
- }
665
- catch (e) {
666
- // verify if it is an auth error, maybe we shouldn't fail silently?
667
- // But for checkout flow, the priority is to proceed.
668
- }
669
- // 2. Set as Cart Shipping Address
670
- const cartId = await getCartId();
671
- if (!cartId) {
672
- throw new Error("No existing cart found when setting addresses");
673
- }
674
- const cartData = {
675
- shipping_address: {
676
- first_name: addressData.first_name,
677
- last_name: addressData.last_name,
678
- company: addressData.company,
679
- address_1: addressData.address_1,
680
- address_2: addressData.address_2,
681
- city: addressData.city,
682
- postal_code: addressData.postal_code,
683
- province: addressData.province,
684
- country_code: addressData.country_code,
685
- phone: addressData.phone,
686
- },
687
- email: normalizeCartEmail(formData.get("email")),
688
- };
689
- if (cartData.email && !isValidCartEmail(cartData.email)) {
690
- throw new Error("Please enter a valid email address.");
691
- }
692
- const sameAsBilling = formData.get("same_as_billing");
693
- if (sameAsBilling === "on") {
694
- cartData.billing_address = cartData.shipping_address;
695
- }
696
- else {
697
- // If not same as billing, we should ideally handle billing address too,
698
- // but AddAddressModal usually forces same_as_billing="on" (Line 52 in AddAddressModal).
699
- // If we ever change that, we'll need logic here. For now, AddAddressModal is strictly for "Add New Shippping Address".
700
- }
701
- await updateCart(cartData);
702
- }
703
- catch (e) {
704
- return e.message;
705
- }
706
- revalidateTag("carts");
707
- // No redirect if we are already in checkout to prevent disrupting the user
708
- }
709
- /**
710
- * Updates address in the background without redirecting.
711
- * Used for real-time shipping calculation when pincode is entered.
712
- */
713
- export async function updateAddressSilently(data) {
714
- const cartId = await getCartId();
715
- if (!cartId)
716
- return;
717
- try {
718
- const payload = { ...data };
719
- if (payload.email !== undefined) {
720
- payload.email = normalizeCartEmail(payload.email);
721
- if (payload.email && !isValidCartEmail(payload.email)) {
722
- return { success: false, error: "Invalid email address." };
723
- }
724
- }
725
- const options = await getStoreClientOptions();
726
- await medusaCartUpdate(cartId, payload, options);
727
- // Revalidate tags to ensure CartTotals gets new shipping info
728
- await revalidateCartTags();
729
- return { success: true };
730
- }
731
- catch (e) {
732
- return { success: false };
733
- }
734
- }
735
- /**
736
- * Updates cart metadata silently without triggering a full page revalidation.
737
- */
738
- export async function updateCartMetadataSilently(metadata) {
739
- const cartId = await getCartId();
740
- if (!cartId)
741
- return;
742
- try {
743
- const options = await getStoreClientOptions();
744
- await medusaCartUpdate(cartId, { metadata }, options);
745
- // We intentionally DO NOT call revalidateTag here to prevent page refresh loops
746
- return { success: true };
747
- }
748
- catch (e) {
749
- return { success: false };
750
- }
751
- }
752
- export async function getAbandonedCarts() {
753
- const authHeaders = await getAuthHeaders();
754
- // If no authorization, return empty arrays
755
- if (!("authorization" in authHeaders)) {
756
- return { buyNowCarts: [], reorderCarts: [] };
757
- }
758
- try {
759
- const options = await getStoreClientOptions();
760
- const res = await medusaCartList(options, {
761
- fields: "*items, *items.product, *items.product.thumbnail, *items.variant, *items.metadata, +total",
762
- }).catch(() => null);
763
- let buyNowCarts = [];
764
- let reorderCarts = [];
765
- if (res && res.carts) {
766
- const currentCartId = await getCartId();
767
- const carts = res.carts;
768
- const filteredCarts = carts.filter((c) => c.id !== currentCartId);
769
- const meta = (c) => c.metadata;
770
- buyNowCarts = filteredCarts.filter((c) => meta(c)?.is_buy_now === true);
771
- reorderCarts = filteredCarts.filter((c) => meta(c)?.is_reorder === true);
772
- }
773
- return { buyNowCarts, reorderCarts };
774
- }
775
- catch (e) {
776
- console.error("Failed to fetch abandoned carts:", e);
777
- return { buyNowCarts: [], reorderCarts: [] };
778
- }
779
- }
780
- export async function resumeAbandonedCart(cartId, countryCode) {
781
- // Set as buy now cart so it temporarily overrides the main cart
782
- // without deleting the main cart cookie (_medusa_cart_id)
783
- await setBuyNowCartId(cartId);
784
- redirect(`/${countryCode}/checkout?cart_id=${cartId}`);
785
- }
786
- export async function deleteCart(cartId) {
787
- try {
788
- const options = await getStoreClientOptions();
789
- await medusaCartDelete(cartId, options);
790
- revalidateTag("carts");
791
- return { success: true };
792
- }
793
- catch (e) {
794
- console.error("Failed to delete cart:", e);
795
- return { success: false, error: e.message };
796
- }
797
- }