medusa-storefront-data 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cookies.d.ts +2 -2
- package/dist/cookies.d.ts.map +1 -1
- package/dist/edge.d.ts +3 -0
- package/dist/edge.d.ts.map +1 -0
- package/dist/edge.js +1 -0
- package/dist/middleware.d.ts +3 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +1 -0
- package/dist/server/cart.d.ts +9 -5
- package/dist/server/cart.d.ts.map +1 -1
- package/dist/server/cart.js +164 -194
- package/dist/server/categories.d.ts +3 -2
- package/dist/server/categories.d.ts.map +1 -1
- package/dist/server/categories.js +14 -51
- package/dist/server/collections.d.ts.map +1 -1
- package/dist/server/collections.js +16 -61
- package/dist/server/contact.d.ts +34 -0
- package/dist/server/contact.d.ts.map +1 -0
- package/dist/server/contact.js +57 -0
- package/dist/server/customer.d.ts +7 -7
- package/dist/server/customer.d.ts.map +1 -1
- package/dist/server/customer.js +96 -145
- package/dist/server/dynamic-config.d.ts.map +1 -1
- package/dist/server/dynamic-config.js +38 -12
- package/dist/server/fulfillment.d.ts +4 -3
- package/dist/server/fulfillment.d.ts.map +1 -1
- package/dist/server/fulfillment.js +16 -41
- package/dist/server/guest.d.ts +35 -63
- package/dist/server/guest.d.ts.map +1 -1
- package/dist/server/guest.js +81 -202
- package/dist/server/home.d.ts +15 -0
- package/dist/server/home.d.ts.map +1 -0
- package/dist/server/home.js +45 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/locale-actions.d.ts +1 -1
- package/dist/server/locale-actions.d.ts.map +1 -1
- package/dist/server/locale-actions.js +8 -13
- package/dist/server/locales.d.ts +2 -4
- package/dist/server/locales.d.ts.map +1 -1
- package/dist/server/locales.js +5 -13
- package/dist/server/orders.d.ts +5 -11
- package/dist/server/orders.d.ts.map +1 -1
- package/dist/server/orders.js +126 -267
- package/dist/server/payment-details.d.ts +4 -4
- package/dist/server/payment-details.d.ts.map +1 -1
- package/dist/server/payment-details.js +17 -42
- package/dist/server/payment.d.ts +2 -1
- package/dist/server/payment.d.ts.map +1 -1
- package/dist/server/payment.js +9 -21
- package/dist/server/pincode.d.ts +7 -0
- package/dist/server/pincode.d.ts.map +1 -0
- package/dist/server/pincode.js +30 -0
- package/dist/server/products.d.ts +15 -19
- package/dist/server/products.d.ts.map +1 -1
- package/dist/server/products.js +47 -178
- package/dist/server/regions.d.ts +1 -1
- package/dist/server/regions.d.ts.map +1 -1
- package/dist/server/regions.js +6 -3
- package/dist/server/returns.d.ts +4 -4
- package/dist/server/returns.d.ts.map +1 -1
- package/dist/server/returns.js +50 -154
- package/dist/server/swaps.d.ts +7 -6
- package/dist/server/swaps.d.ts.map +1 -1
- package/dist/server/swaps.js +23 -57
- package/dist/server/variants.d.ts.map +1 -1
- package/dist/server/variants.js +11 -22
- package/dist/server/wishlist.d.ts +11 -0
- package/dist/server/wishlist.d.ts.map +1 -0
- package/dist/server/wishlist.js +49 -0
- package/dist/util/get-locale-header.d.ts +1 -1
- package/dist/util/revalidate-cart.d.ts +2 -0
- package/dist/util/revalidate-cart.d.ts.map +1 -0
- package/dist/util/revalidate-cart.js +8 -0
- package/dist/util/sort-products.d.ts +3 -0
- package/dist/util/sort-products.d.ts.map +1 -0
- package/dist/util/sort-products.js +1 -0
- package/dist/util/store-client.d.ts +13 -0
- package/dist/util/store-client.d.ts.map +1 -0
- package/dist/util/store-client.js +77 -0
- package/package.json +95 -37
- package/src/edge.ts +2 -0
- package/src/middleware.ts +2 -2
- package/src/server/cart.ts +214 -267
- package/src/server/categories.ts +19 -72
- package/src/server/collections.ts +25 -82
- package/src/server/contact.ts +92 -0
- package/src/server/customer.ts +146 -190
- package/src/server/dynamic-config.ts +38 -12
- package/src/server/fulfillment.ts +27 -53
- package/src/server/guest.ts +159 -276
- package/src/server/home.ts +68 -0
- package/src/server/index.ts +1 -0
- package/src/server/locale-actions.ts +8 -15
- package/src/server/locales.ts +6 -18
- package/src/server/orders.ts +167 -337
- package/src/server/payment-details.ts +24 -52
- package/src/server/payment.ts +8 -28
- package/src/server/pincode.ts +49 -0
- package/src/server/products.ts +72 -235
- package/src/server/regions.ts +10 -6
- package/src/server/returns.ts +75 -189
- package/src/server/swaps.ts +94 -123
- package/src/server/variants.ts +9 -28
- package/src/server/wishlist.ts +1 -1
- package/src/util/revalidate-cart.ts +10 -0
- package/src/util/sort-products.ts +2 -47
- package/src/util/store-client.ts +93 -0
- package/src/services/middleware.ts +0 -54
package/src/server/cart.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use server"
|
|
2
2
|
|
|
3
|
+
import type { FetchArgs } from "@medusajs/js-sdk"
|
|
3
4
|
import { sdk } from "../config"
|
|
4
5
|
import medusaError from "../util/medusa-error"
|
|
5
6
|
import { HttpTypes } from "@medusajs/types"
|
|
6
7
|
import { revalidateTag, revalidatePath } from "next/cache"
|
|
7
8
|
import { redirect } from "next/navigation"
|
|
8
|
-
import { headers } from "next/headers"
|
|
9
|
+
import { headers as nextHeaders } from "next/headers"
|
|
9
10
|
import {
|
|
10
11
|
getAuthHeaders,
|
|
11
12
|
getCacheOptions,
|
|
@@ -20,11 +21,52 @@ import {
|
|
|
20
21
|
removeBuyNowCartId,
|
|
21
22
|
} from "../cookies"
|
|
22
23
|
import { getRegion } from "./regions"
|
|
24
|
+
|
|
25
|
+
function normalizeCartEmail(email: unknown): string | undefined {
|
|
26
|
+
if (typeof email !== "string") return undefined
|
|
27
|
+
const normalized = email.trim().toLowerCase()
|
|
28
|
+
return normalized || undefined
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isValidCartEmail(email: string): boolean {
|
|
32
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
|
|
33
|
+
}
|
|
23
34
|
import { getLocale } from "./locale-actions"
|
|
24
35
|
import { retrieveCustomer, transferCart } from "./customer"
|
|
36
|
+
import {
|
|
37
|
+
medusaCartCreate,
|
|
38
|
+
medusaCartRetrieve,
|
|
39
|
+
medusaCartUpdate,
|
|
40
|
+
medusaCartAddLineItem,
|
|
41
|
+
medusaCartUpdateLineItem,
|
|
42
|
+
medusaCartRemoveLineItem,
|
|
43
|
+
medusaCartApplyPromotions,
|
|
44
|
+
medusaCartAddShippingMethod,
|
|
45
|
+
medusaCartComplete,
|
|
46
|
+
medusaCartSkipMerge,
|
|
47
|
+
medusaCartDelete,
|
|
48
|
+
medusaCartList,
|
|
49
|
+
medusaShippingOptionsList,
|
|
50
|
+
MEDUSA_STORE_CART_DETAIL_FIELDS,
|
|
51
|
+
} from "medusa-services/cart"
|
|
52
|
+
import {
|
|
53
|
+
medusaCustomerCreateAddress,
|
|
54
|
+
medusaCustomerRetrieve,
|
|
55
|
+
medusaCustomerUpdateAddress,
|
|
56
|
+
} from "medusa-services/customer"
|
|
57
|
+
import { medusaPaymentSessionInitiate } from "medusa-services/payment"
|
|
58
|
+
import { getStoreCartClientOptions } from "../util/store-client"
|
|
59
|
+
import { revalidateCartTags } from "../util/revalidate-cart"
|
|
25
60
|
|
|
26
61
|
import { cache } from "react"
|
|
27
62
|
|
|
63
|
+
function throwCartError(error: unknown): never {
|
|
64
|
+
if (error && typeof error === "object" && "response" in error) {
|
|
65
|
+
medusaError(error)
|
|
66
|
+
}
|
|
67
|
+
throw error instanceof Error ? error : new Error(String(error))
|
|
68
|
+
}
|
|
69
|
+
|
|
28
70
|
/**
|
|
29
71
|
* Retrieves a cart by its ID. If no ID is provided, it will use the cart ID from the cookies.
|
|
30
72
|
* @param cartId - optional - The ID of the cart to retrieve.
|
|
@@ -39,22 +81,18 @@ export const retrieveCart = cache(
|
|
|
39
81
|
// If we're not explicitly asking for a specific cartId and we have an active cart
|
|
40
82
|
if (!cartId && id) {
|
|
41
83
|
try {
|
|
42
|
-
const headerList = await
|
|
84
|
+
const headerList = await nextHeaders()
|
|
43
85
|
const pathname = headerList.get("x-pathname") || headerList.get("referer") || ""
|
|
44
86
|
|
|
45
87
|
// Skip metadata check if we are clearly in checkout to avoid extra API call
|
|
46
88
|
if (!pathname.includes("/checkout")) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
method: "GET",
|
|
50
|
-
query: { fields: "metadata" },
|
|
51
|
-
headers: await getAuthHeaders(),
|
|
52
|
-
cache: "no-store",
|
|
53
|
-
})
|
|
89
|
+
const options = await getStoreCartClientOptions()
|
|
90
|
+
const currentCart = await medusaCartRetrieve(id, options, { fields: "metadata" })
|
|
54
91
|
.then(({ cart }) => cart)
|
|
55
92
|
.catch(() => null)
|
|
56
93
|
|
|
57
|
-
|
|
94
|
+
const cartMeta = currentCart?.metadata as Record<string, unknown> | null | undefined
|
|
95
|
+
if (cartMeta?.is_buy_now || cartMeta?.is_reorder) {
|
|
58
96
|
await removeBuyNowCartId()
|
|
59
97
|
id = await getCartId() // Re-fetch ID which will now fall back to the real main cart
|
|
60
98
|
revalidateTag("carts")
|
|
@@ -65,14 +103,13 @@ export const retrieveCart = cache(
|
|
|
65
103
|
}
|
|
66
104
|
}
|
|
67
105
|
|
|
68
|
-
fields ??=
|
|
69
|
-
"*items, *region, *items.product, *items.product.thumbnail, *items.product.images, *items.product.options, *items.product.variants, +items.product.variants.inventory_quantity, +items.product.variants.manage_inventory, +items.product.variants.allow_backorder, *items.product.variants.options, *items.variant, +items.variant.inventory_quantity, +items.variant.manage_inventory, +items.variant.allow_backorder, *items.variant.images, *items.variant.product, *items.variant.product.thumbnail, *items.variant.product.images, *items.variant.options, *items.thumbnail, *items.metadata, +items.total, +items.adjustments, *promotions, +shipping_methods.name, +shipping_methods.adjustments"
|
|
106
|
+
fields ??= MEDUSA_STORE_CART_DETAIL_FIELDS
|
|
70
107
|
|
|
71
108
|
if (!id) {
|
|
72
109
|
return null
|
|
73
110
|
}
|
|
74
111
|
|
|
75
|
-
const
|
|
112
|
+
const authHeaders = {
|
|
76
113
|
...(await getAuthHeaders()),
|
|
77
114
|
}
|
|
78
115
|
|
|
@@ -86,10 +123,10 @@ export const retrieveCart = cache(
|
|
|
86
123
|
query: {
|
|
87
124
|
fields,
|
|
88
125
|
},
|
|
89
|
-
headers,
|
|
126
|
+
headers: authHeaders,
|
|
90
127
|
next,
|
|
91
128
|
cache: "no-store",
|
|
92
|
-
})
|
|
129
|
+
} as FetchArgs & { next?: typeof next; cache?: RequestCache })
|
|
93
130
|
.then(({ cart }: { cart: HttpTypes.StoreCart }) => {
|
|
94
131
|
return cart
|
|
95
132
|
})
|
|
@@ -106,19 +143,15 @@ export async function getOrSetCart(countryCode: string) {
|
|
|
106
143
|
}
|
|
107
144
|
|
|
108
145
|
let cart = await retrieveCart(undefined, "id,region_id")
|
|
109
|
-
|
|
110
|
-
const headers = {
|
|
111
|
-
...(await getAuthHeaders()),
|
|
112
|
-
}
|
|
146
|
+
const options = await getStoreCartClientOptions()
|
|
113
147
|
|
|
114
148
|
if (!cart) {
|
|
115
149
|
const locale = await getLocale()
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
cart = cartResp.cart
|
|
150
|
+
const { cart: createdCart } = await medusaCartCreate(options, {
|
|
151
|
+
region_id: region.id,
|
|
152
|
+
locale: locale || undefined,
|
|
153
|
+
})
|
|
154
|
+
cart = createdCart as unknown as HttpTypes.StoreCart
|
|
122
155
|
|
|
123
156
|
await setCartId(cart.id)
|
|
124
157
|
|
|
@@ -127,7 +160,7 @@ export async function getOrSetCart(countryCode: string) {
|
|
|
127
160
|
}
|
|
128
161
|
|
|
129
162
|
if (cart && cart?.region_id !== region.id) {
|
|
130
|
-
await
|
|
163
|
+
await medusaCartUpdate(cart.id, { region_id: region.id }, options)
|
|
131
164
|
const cartCacheTag = await getCacheTag("carts")
|
|
132
165
|
revalidateTag(cartCacheTag)
|
|
133
166
|
}
|
|
@@ -142,22 +175,14 @@ export async function updateCart(data: HttpTypes.StoreUpdateCart) {
|
|
|
142
175
|
throw new Error("No existing cart found, please create one before updating")
|
|
143
176
|
}
|
|
144
177
|
|
|
145
|
-
|
|
146
|
-
|
|
178
|
+
try {
|
|
179
|
+
const options = await getStoreCartClientOptions()
|
|
180
|
+
const { cart } = await medusaCartUpdate(cartId, data as Record<string, unknown>, options)
|
|
181
|
+
await revalidateCartTags()
|
|
182
|
+
return cart as unknown as HttpTypes.StoreCart
|
|
183
|
+
} catch (e) {
|
|
184
|
+
throwCartError(e)
|
|
147
185
|
}
|
|
148
|
-
|
|
149
|
-
return sdk.store.cart
|
|
150
|
-
.update(cartId, data, {}, headers)
|
|
151
|
-
.then(async ({ cart }: { cart: HttpTypes.StoreCart }) => {
|
|
152
|
-
const cartCacheTag = await getCacheTag("carts")
|
|
153
|
-
revalidateTag(cartCacheTag)
|
|
154
|
-
|
|
155
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment")
|
|
156
|
-
revalidateTag(fulfillmentCacheTag)
|
|
157
|
-
|
|
158
|
-
return cart
|
|
159
|
-
})
|
|
160
|
-
.catch(medusaError)
|
|
161
186
|
}
|
|
162
187
|
|
|
163
188
|
export async function addToCart({
|
|
@@ -179,28 +204,13 @@ export async function addToCart({
|
|
|
179
204
|
throw new Error("Error retrieving or creating cart")
|
|
180
205
|
}
|
|
181
206
|
|
|
182
|
-
|
|
183
|
-
|
|
207
|
+
try {
|
|
208
|
+
const options = await getStoreCartClientOptions()
|
|
209
|
+
await medusaCartAddLineItem(cart.id, { variant_id: variantId, quantity }, options)
|
|
210
|
+
await revalidateCartTags()
|
|
211
|
+
} catch (e) {
|
|
212
|
+
throwCartError(e)
|
|
184
213
|
}
|
|
185
|
-
|
|
186
|
-
await sdk.store.cart
|
|
187
|
-
.createLineItem(
|
|
188
|
-
cart.id,
|
|
189
|
-
{
|
|
190
|
-
variant_id: variantId,
|
|
191
|
-
quantity,
|
|
192
|
-
},
|
|
193
|
-
{},
|
|
194
|
-
headers
|
|
195
|
-
)
|
|
196
|
-
.then(async () => {
|
|
197
|
-
const cartCacheTag = await getCacheTag("carts")
|
|
198
|
-
revalidateTag(cartCacheTag)
|
|
199
|
-
|
|
200
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment")
|
|
201
|
-
revalidateTag(fulfillmentCacheTag)
|
|
202
|
-
})
|
|
203
|
-
.catch(medusaError)
|
|
204
214
|
}
|
|
205
215
|
|
|
206
216
|
export async function buyNow({
|
|
@@ -222,23 +232,15 @@ export async function buyNow({
|
|
|
222
232
|
throw new Error(`Region not found for country code: ${countryCode}`)
|
|
223
233
|
}
|
|
224
234
|
|
|
225
|
-
const
|
|
226
|
-
...(await getAuthHeaders()),
|
|
227
|
-
}
|
|
228
|
-
|
|
235
|
+
const options = await getStoreCartClientOptions()
|
|
229
236
|
const locale = await getLocale()
|
|
230
237
|
|
|
231
238
|
// 1. Create a NEW cart regardless of existing one
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
},
|
|
238
|
-
{},
|
|
239
|
-
headers
|
|
240
|
-
)
|
|
241
|
-
const cart = cartResp.cart
|
|
239
|
+
const { cart } = await medusaCartCreate(options, {
|
|
240
|
+
region_id: region.id,
|
|
241
|
+
locale: locale || undefined,
|
|
242
|
+
metadata: { is_buy_now: true },
|
|
243
|
+
})
|
|
242
244
|
|
|
243
245
|
// Save the new cart id in "buy_now_cart_id" cookie
|
|
244
246
|
await removeBuyNowCartId()
|
|
@@ -246,25 +248,13 @@ export async function buyNow({
|
|
|
246
248
|
|
|
247
249
|
// Ensure this new cart is not merged with existing ones
|
|
248
250
|
try {
|
|
249
|
-
await
|
|
250
|
-
method: "POST",
|
|
251
|
-
body: { cart_id: cart.id },
|
|
252
|
-
headers,
|
|
253
|
-
})
|
|
251
|
+
await medusaCartSkipMerge(cart.id, options)
|
|
254
252
|
} catch (e) {
|
|
255
253
|
console.error("Failed to skip cart merge for buy now cart:", e)
|
|
256
254
|
}
|
|
257
255
|
|
|
258
256
|
// 2. Add the item to this new cart
|
|
259
|
-
await
|
|
260
|
-
cart.id,
|
|
261
|
-
{
|
|
262
|
-
variant_id: variantId,
|
|
263
|
-
quantity,
|
|
264
|
-
},
|
|
265
|
-
{},
|
|
266
|
-
headers
|
|
267
|
-
)
|
|
257
|
+
await medusaCartAddLineItem(cart.id, { variant_id: variantId, quantity }, options)
|
|
268
258
|
|
|
269
259
|
// 3. (REMOVED: No longer overwriting the main cart ID, because getCartId handles buy_now_cart_id priority)
|
|
270
260
|
|
|
@@ -278,45 +268,43 @@ export async function buyNow({
|
|
|
278
268
|
if (defaultAddress) {
|
|
279
269
|
try {
|
|
280
270
|
// Set addresses
|
|
281
|
-
await
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
271
|
+
await medusaCartUpdate(
|
|
272
|
+
cart.id,
|
|
273
|
+
{
|
|
274
|
+
shipping_address: {
|
|
275
|
+
first_name: defaultAddress.first_name,
|
|
276
|
+
last_name: defaultAddress.last_name,
|
|
277
|
+
address_1: defaultAddress.address_1,
|
|
278
|
+
address_2: defaultAddress.address_2,
|
|
279
|
+
city: defaultAddress.city,
|
|
280
|
+
country_code: defaultAddress.country_code,
|
|
281
|
+
postal_code: defaultAddress.postal_code,
|
|
282
|
+
province: defaultAddress.province,
|
|
283
|
+
phone: defaultAddress.phone,
|
|
284
|
+
company: defaultAddress.company,
|
|
285
|
+
},
|
|
286
|
+
billing_address: {
|
|
287
|
+
first_name: defaultAddress.first_name,
|
|
288
|
+
last_name: defaultAddress.last_name,
|
|
289
|
+
address_1: defaultAddress.address_1,
|
|
290
|
+
address_2: defaultAddress.address_2,
|
|
291
|
+
city: defaultAddress.city,
|
|
292
|
+
country_code: defaultAddress.country_code,
|
|
293
|
+
postal_code: defaultAddress.postal_code,
|
|
294
|
+
province: defaultAddress.province,
|
|
295
|
+
phone: defaultAddress.phone,
|
|
296
|
+
company: defaultAddress.company,
|
|
297
|
+
},
|
|
298
|
+
email: customer?.email ?? "",
|
|
305
299
|
},
|
|
306
|
-
|
|
307
|
-
|
|
300
|
+
options
|
|
301
|
+
)
|
|
308
302
|
|
|
309
303
|
// Fetch and set first shipping method
|
|
310
|
-
const { shipping_options } = await
|
|
311
|
-
shipping_options: HttpTypes.StoreCartShippingOption[]
|
|
312
|
-
}>("/store/shipping-options", {
|
|
313
|
-
query: { cart_id: cart.id },
|
|
314
|
-
headers,
|
|
315
|
-
cache: "no-store",
|
|
316
|
-
})
|
|
304
|
+
const { shipping_options } = await medusaShippingOptionsList(cart.id, options)
|
|
317
305
|
|
|
318
306
|
if (shipping_options?.length > 0) {
|
|
319
|
-
await
|
|
307
|
+
await medusaCartAddShippingMethod(cart.id, shipping_options[0].id, options)
|
|
320
308
|
skipToPayment = true
|
|
321
309
|
}
|
|
322
310
|
} catch (e) {
|
|
@@ -354,20 +342,13 @@ export async function updateLineItem({
|
|
|
354
342
|
throw new Error("Missing cart ID when updating line item")
|
|
355
343
|
}
|
|
356
344
|
|
|
357
|
-
|
|
358
|
-
|
|
345
|
+
try {
|
|
346
|
+
const options = await getStoreCartClientOptions()
|
|
347
|
+
await medusaCartUpdateLineItem(cartId, lineId, { quantity }, options)
|
|
348
|
+
await revalidateCartTags()
|
|
349
|
+
} catch (e) {
|
|
350
|
+
throwCartError(e)
|
|
359
351
|
}
|
|
360
|
-
|
|
361
|
-
await sdk.store.cart
|
|
362
|
-
.updateLineItem(cartId, lineId, { quantity }, {}, headers)
|
|
363
|
-
.then(async () => {
|
|
364
|
-
const cartCacheTag = await getCacheTag("carts")
|
|
365
|
-
revalidateTag(cartCacheTag)
|
|
366
|
-
|
|
367
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment")
|
|
368
|
-
revalidateTag(fulfillmentCacheTag)
|
|
369
|
-
})
|
|
370
|
-
.catch(medusaError)
|
|
371
352
|
}
|
|
372
353
|
|
|
373
354
|
export async function deleteLineItem(lineId: string) {
|
|
@@ -381,20 +362,13 @@ export async function deleteLineItem(lineId: string) {
|
|
|
381
362
|
throw new Error("Missing cart ID when deleting line item")
|
|
382
363
|
}
|
|
383
364
|
|
|
384
|
-
|
|
385
|
-
|
|
365
|
+
try {
|
|
366
|
+
const options = await getStoreCartClientOptions()
|
|
367
|
+
await medusaCartRemoveLineItem(cartId, lineId, options)
|
|
368
|
+
await revalidateCartTags()
|
|
369
|
+
} catch (e) {
|
|
370
|
+
throwCartError(e)
|
|
386
371
|
}
|
|
387
|
-
|
|
388
|
-
await sdk.store.cart
|
|
389
|
-
.deleteLineItem(cartId, lineId, {}, headers)
|
|
390
|
-
.then(async () => {
|
|
391
|
-
const cartCacheTag = await getCacheTag("carts")
|
|
392
|
-
revalidateTag(cartCacheTag)
|
|
393
|
-
|
|
394
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment")
|
|
395
|
-
revalidateTag(fulfillmentCacheTag)
|
|
396
|
-
})
|
|
397
|
-
.catch(medusaError)
|
|
398
372
|
}
|
|
399
373
|
|
|
400
374
|
export async function updateLineItemVariant({
|
|
@@ -434,17 +408,14 @@ export async function setShippingMethod({
|
|
|
434
408
|
cartId: string
|
|
435
409
|
shippingMethodId: string
|
|
436
410
|
}) {
|
|
437
|
-
|
|
438
|
-
|
|
411
|
+
try {
|
|
412
|
+
const options = await getStoreCartClientOptions()
|
|
413
|
+
await medusaCartAddShippingMethod(cartId, shippingMethodId, options)
|
|
414
|
+
const cartCacheTag = await getCacheTag("carts")
|
|
415
|
+
revalidateTag(cartCacheTag)
|
|
416
|
+
} catch (e) {
|
|
417
|
+
throwCartError(e)
|
|
439
418
|
}
|
|
440
|
-
|
|
441
|
-
return sdk.store.cart
|
|
442
|
-
.addShippingMethod(cartId, { option_id: shippingMethodId }, {}, headers)
|
|
443
|
-
.then(async () => {
|
|
444
|
-
const cartCacheTag = await getCacheTag("carts")
|
|
445
|
-
revalidateTag(cartCacheTag)
|
|
446
|
-
})
|
|
447
|
-
.catch(medusaError)
|
|
448
419
|
}
|
|
449
420
|
|
|
450
421
|
/**
|
|
@@ -457,12 +428,9 @@ export async function setShippingMethodSilently({
|
|
|
457
428
|
cartId: string
|
|
458
429
|
shippingMethodId: string
|
|
459
430
|
}) {
|
|
460
|
-
const headers = {
|
|
461
|
-
...(await getAuthHeaders()),
|
|
462
|
-
}
|
|
463
|
-
|
|
464
431
|
try {
|
|
465
|
-
|
|
432
|
+
const options = await getStoreCartClientOptions()
|
|
433
|
+
await medusaCartAddShippingMethod(cartId, shippingMethodId, options)
|
|
466
434
|
return { success: true }
|
|
467
435
|
} catch (e) {
|
|
468
436
|
return { success: false }
|
|
@@ -474,10 +442,6 @@ export async function initiatePaymentSession(
|
|
|
474
442
|
cart: HttpTypes.StoreCart,
|
|
475
443
|
data: HttpTypes.StoreInitializePaymentSession
|
|
476
444
|
) {
|
|
477
|
-
const headers = {
|
|
478
|
-
...(await getAuthHeaders()),
|
|
479
|
-
}
|
|
480
|
-
|
|
481
445
|
// 1. RE-FETCH cart with NO CACHE to ensure we have the latest data from the DB
|
|
482
446
|
const latestCart = await retrieveCart(cart.id)
|
|
483
447
|
if (!latestCart) throw new Error("Cart not found")
|
|
@@ -526,13 +490,17 @@ export async function initiatePaymentSession(
|
|
|
526
490
|
}
|
|
527
491
|
|
|
528
492
|
if (Object.keys(addressUpdates).length > 0) {
|
|
529
|
-
|
|
493
|
+
const options = await getStoreCartClientOptions()
|
|
494
|
+
await medusaCartUpdate(latestCart.id, addressUpdates, options)
|
|
530
495
|
}
|
|
531
496
|
}
|
|
532
497
|
|
|
533
|
-
// 3. Final re-fetch (direct
|
|
534
|
-
const
|
|
535
|
-
const
|
|
498
|
+
// 3. Final re-fetch (direct call to bypass any lib-level cache)
|
|
499
|
+
const options = await getStoreCartClientOptions()
|
|
500
|
+
const { cart: finalCartRaw } = await medusaCartRetrieve(cart.id, options, {
|
|
501
|
+
fields: "*shipping_address,*billing_address",
|
|
502
|
+
})
|
|
503
|
+
const finalCart = finalCartRaw as unknown as HttpTypes.StoreCart
|
|
536
504
|
|
|
537
505
|
// 4. PRE-FLIGHT VALIDATION: Only strictly block for Razorpay, be more lenient for COD
|
|
538
506
|
const isRazorpayProvider = data.provider_id.includes("razorpay")
|
|
@@ -561,17 +529,19 @@ export async function initiatePaymentSession(
|
|
|
561
529
|
}
|
|
562
530
|
}
|
|
563
531
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
revalidateTag(cartCacheTag)
|
|
569
|
-
return resp
|
|
570
|
-
})
|
|
571
|
-
.catch((e) => {
|
|
572
|
-
const errorMsg = e.message || e.response?.data?.message || "Unknown error"
|
|
573
|
-
throw new Error(`Razorpay Initialization Failed: ${errorMsg}`)
|
|
532
|
+
try {
|
|
533
|
+
await medusaPaymentSessionInitiate(finalCart.id, enhancedData, options)
|
|
534
|
+
const { cart: refreshedCart } = await medusaCartRetrieve(finalCart.id, options, {
|
|
535
|
+
fields: `${MEDUSA_STORE_CART_DETAIL_FIELDS}, *payment_collection, *payment_collection.payment_sessions`,
|
|
574
536
|
})
|
|
537
|
+
const cartCacheTag = await getCacheTag("carts")
|
|
538
|
+
revalidateTag(cartCacheTag)
|
|
539
|
+
return refreshedCart as unknown as HttpTypes.StoreCart
|
|
540
|
+
} catch (e: any) {
|
|
541
|
+
const errorMsg = e.message || e.response?.data?.message || "Unknown error"
|
|
542
|
+
const label = isRazorpayProvider ? "Razorpay" : "Payment"
|
|
543
|
+
throw new Error(`${label} initialization failed: ${errorMsg}`)
|
|
544
|
+
}
|
|
575
545
|
}
|
|
576
546
|
|
|
577
547
|
export async function applyPromotions(codes: string[]) {
|
|
@@ -581,22 +551,14 @@ export async function applyPromotions(codes: string[]) {
|
|
|
581
551
|
throw new Error("No existing cart found")
|
|
582
552
|
}
|
|
583
553
|
|
|
584
|
-
|
|
585
|
-
|
|
554
|
+
try {
|
|
555
|
+
const options = await getStoreCartClientOptions()
|
|
556
|
+
const { cart } = await medusaCartApplyPromotions(cartId, codes, options)
|
|
557
|
+
await revalidateCartTags()
|
|
558
|
+
return cart as unknown as HttpTypes.StoreCart
|
|
559
|
+
} catch (e) {
|
|
560
|
+
throwCartError(e)
|
|
586
561
|
}
|
|
587
|
-
|
|
588
|
-
return sdk.store.cart
|
|
589
|
-
.update(cartId, { promo_codes: codes }, {}, headers)
|
|
590
|
-
.then(async ({ cart }) => {
|
|
591
|
-
const cartCacheTag = await getCacheTag("carts")
|
|
592
|
-
revalidateTag(cartCacheTag)
|
|
593
|
-
|
|
594
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment")
|
|
595
|
-
revalidateTag(fulfillmentCacheTag)
|
|
596
|
-
|
|
597
|
-
return cart
|
|
598
|
-
})
|
|
599
|
-
.catch(medusaError)
|
|
600
562
|
}
|
|
601
563
|
|
|
602
564
|
export async function applyGiftCard(code: string) {
|
|
@@ -693,22 +655,21 @@ export async function setAddresses(currentState: unknown, formData: FormData) {
|
|
|
693
655
|
|
|
694
656
|
const data = {
|
|
695
657
|
shipping_address: shippingAddress,
|
|
696
|
-
email: formData.get("email"),
|
|
658
|
+
email: normalizeCartEmail(formData.get("email")),
|
|
697
659
|
} as any
|
|
698
660
|
|
|
661
|
+
if (data.email && !isValidCartEmail(data.email)) {
|
|
662
|
+
throw new Error("Please enter a valid email address.")
|
|
663
|
+
}
|
|
664
|
+
|
|
699
665
|
|
|
700
666
|
|
|
701
667
|
// Save address to customer profile if logged in
|
|
702
668
|
const authHeaders = await getAuthHeaders()
|
|
703
669
|
if (authHeaders && "authorization" in authHeaders) {
|
|
704
670
|
try {
|
|
705
|
-
|
|
706
|
-
const { customer } = await
|
|
707
|
-
method: "GET",
|
|
708
|
-
query: { fields: "*addresses" },
|
|
709
|
-
headers: authHeaders as Record<string, string>,
|
|
710
|
-
cache: "no-store",
|
|
711
|
-
})
|
|
671
|
+
const options = await getStoreCartClientOptions()
|
|
672
|
+
const { customer } = await medusaCustomerRetrieve(options, { fields: "*addresses" })
|
|
712
673
|
|
|
713
674
|
const addressExists = customer?.addresses?.some((a: any) =>
|
|
714
675
|
a.address_1 === shippingAddress.address_1 &&
|
|
@@ -719,7 +680,7 @@ export async function setAddresses(currentState: unknown, formData: FormData) {
|
|
|
719
680
|
)
|
|
720
681
|
|
|
721
682
|
if (!addressExists) {
|
|
722
|
-
await
|
|
683
|
+
await medusaCustomerCreateAddress(shippingAddress, options)
|
|
723
684
|
const customerCacheTag = await getCacheTag("customers")
|
|
724
685
|
revalidateTag(customerCacheTag)
|
|
725
686
|
}
|
|
@@ -768,22 +729,19 @@ export async function placeOrder(cartId?: string) {
|
|
|
768
729
|
throw new Error("No existing cart found when placing an order")
|
|
769
730
|
}
|
|
770
731
|
|
|
771
|
-
|
|
772
|
-
|
|
732
|
+
let cartRes
|
|
733
|
+
try {
|
|
734
|
+
const options = await getStoreCartClientOptions()
|
|
735
|
+
cartRes = await medusaCartComplete(id, options)
|
|
736
|
+
const cartCacheTag = await getCacheTag("carts")
|
|
737
|
+
revalidateTag(cartCacheTag)
|
|
738
|
+
} catch (e) {
|
|
739
|
+
throwCartError(e)
|
|
773
740
|
}
|
|
774
741
|
|
|
775
|
-
const cartRes = await sdk.store.cart
|
|
776
|
-
.complete(id, {}, headers)
|
|
777
|
-
.then(async (cartRes) => {
|
|
778
|
-
const cartCacheTag = await getCacheTag("carts")
|
|
779
|
-
revalidateTag(cartCacheTag)
|
|
780
|
-
return cartRes
|
|
781
|
-
})
|
|
782
|
-
.catch(medusaError)
|
|
783
|
-
|
|
784
742
|
if (cartRes?.type === "order") {
|
|
785
|
-
const
|
|
786
|
-
|
|
743
|
+
const order = cartRes.order as HttpTypes.StoreOrder
|
|
744
|
+
const countryCode = order.shipping_address?.country_code?.toLowerCase()
|
|
787
745
|
|
|
788
746
|
const orderCacheTag = await getCacheTag("orders")
|
|
789
747
|
revalidateTag(orderCacheTag)
|
|
@@ -802,10 +760,10 @@ export async function placeOrder(cartId?: string) {
|
|
|
802
760
|
await removeCartId()
|
|
803
761
|
}
|
|
804
762
|
|
|
805
|
-
redirect(`/${countryCode}/order/${
|
|
763
|
+
redirect(`/${countryCode}/order/${order.id}/confirmed`)
|
|
806
764
|
}
|
|
807
765
|
|
|
808
|
-
return cartRes.cart
|
|
766
|
+
return cartRes.cart as unknown as HttpTypes.StoreCart
|
|
809
767
|
}
|
|
810
768
|
|
|
811
769
|
/**
|
|
@@ -852,15 +810,11 @@ export async function listCartOptions() {
|
|
|
852
810
|
next,
|
|
853
811
|
headers,
|
|
854
812
|
cache: "force-cache",
|
|
855
|
-
})
|
|
813
|
+
} as FetchArgs & { next?: typeof next; cache?: RequestCache })
|
|
856
814
|
}
|
|
857
815
|
|
|
858
816
|
export async function addCustomerAddressToCart(currentState: unknown, formData: FormData) {
|
|
859
817
|
try {
|
|
860
|
-
const headers = {
|
|
861
|
-
...(await getAuthHeaders()),
|
|
862
|
-
}
|
|
863
|
-
|
|
864
818
|
const shippingCountryCode = (formData.get("shipping_address.country_code") as string)?.toLowerCase() || "in"
|
|
865
819
|
|
|
866
820
|
// Parse address data from formData (which uses shipping_address. prefix)
|
|
@@ -886,10 +840,11 @@ export async function addCustomerAddressToCart(currentState: unknown, formData:
|
|
|
886
840
|
// 1. Add/Update Customer Address Book
|
|
887
841
|
// We try/catch this separately so if it fails (e.g. user not logged in), we still try to proceed with checkout
|
|
888
842
|
try {
|
|
843
|
+
const options = await getStoreCartClientOptions()
|
|
889
844
|
if (addressId) {
|
|
890
|
-
await
|
|
845
|
+
await medusaCustomerUpdateAddress(addressId, addressData, options)
|
|
891
846
|
} else {
|
|
892
|
-
await
|
|
847
|
+
await medusaCustomerCreateAddress(addressData, options)
|
|
893
848
|
}
|
|
894
849
|
const customerCacheTag = await getCacheTag("customers")
|
|
895
850
|
revalidateTag(customerCacheTag)
|
|
@@ -918,9 +873,13 @@ export async function addCustomerAddressToCart(currentState: unknown, formData:
|
|
|
918
873
|
country_code: addressData.country_code,
|
|
919
874
|
phone: addressData.phone,
|
|
920
875
|
},
|
|
921
|
-
email: formData.get("email"),
|
|
876
|
+
email: normalizeCartEmail(formData.get("email")),
|
|
922
877
|
} as any
|
|
923
878
|
|
|
879
|
+
if (cartData.email && !isValidCartEmail(cartData.email)) {
|
|
880
|
+
throw new Error("Please enter a valid email address.")
|
|
881
|
+
}
|
|
882
|
+
|
|
924
883
|
const sameAsBilling = formData.get("same_as_billing")
|
|
925
884
|
if (sameAsBilling === "on") {
|
|
926
885
|
cartData.billing_address = cartData.shipping_address
|
|
@@ -949,18 +908,19 @@ export async function updateAddressSilently(data: any) {
|
|
|
949
908
|
if (!cartId) return
|
|
950
909
|
|
|
951
910
|
try {
|
|
952
|
-
const
|
|
953
|
-
|
|
911
|
+
const payload = { ...data }
|
|
912
|
+
if (payload.email !== undefined) {
|
|
913
|
+
payload.email = normalizeCartEmail(payload.email)
|
|
914
|
+
if (payload.email && !isValidCartEmail(payload.email)) {
|
|
915
|
+
return { success: false, error: "Invalid email address." }
|
|
916
|
+
}
|
|
954
917
|
}
|
|
955
918
|
|
|
956
|
-
|
|
919
|
+
const options = await getStoreCartClientOptions()
|
|
920
|
+
await medusaCartUpdate(cartId, payload, options)
|
|
957
921
|
|
|
958
922
|
// Revalidate tags to ensure CartTotals gets new shipping info
|
|
959
|
-
|
|
960
|
-
revalidateTag(cartCacheTag)
|
|
961
|
-
|
|
962
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment")
|
|
963
|
-
revalidateTag(fulfillmentCacheTag)
|
|
923
|
+
await revalidateCartTags()
|
|
964
924
|
|
|
965
925
|
return { success: true }
|
|
966
926
|
} catch (e) {
|
|
@@ -975,11 +935,8 @@ export async function updateCartMetadataSilently(metadata: any) {
|
|
|
975
935
|
if (!cartId) return
|
|
976
936
|
|
|
977
937
|
try {
|
|
978
|
-
const
|
|
979
|
-
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
await sdk.store.cart.update(cartId, { metadata }, {}, headers)
|
|
938
|
+
const options = await getStoreCartClientOptions()
|
|
939
|
+
await medusaCartUpdate(cartId, { metadata }, options)
|
|
983
940
|
// We intentionally DO NOT call revalidateTag here to prevent page refresh loops
|
|
984
941
|
return { success: true }
|
|
985
942
|
} catch (e) {
|
|
@@ -988,36 +945,31 @@ export async function updateCartMetadataSilently(metadata: any) {
|
|
|
988
945
|
}
|
|
989
946
|
|
|
990
947
|
export async function getAbandonedCarts() {
|
|
991
|
-
const
|
|
992
|
-
...(await getAuthHeaders()),
|
|
993
|
-
}
|
|
948
|
+
const authHeaders = await getAuthHeaders()
|
|
994
949
|
|
|
995
950
|
// If no authorization, return empty arrays
|
|
996
|
-
if (!
|
|
951
|
+
if (!("authorization" in authHeaders)) {
|
|
997
952
|
return { buyNowCarts: [], reorderCarts: [] }
|
|
998
953
|
}
|
|
999
954
|
|
|
1000
955
|
try {
|
|
1001
|
-
|
|
1002
|
-
const res = await
|
|
1003
|
-
|
|
1004
|
-
query: {
|
|
1005
|
-
fields: "*items, *items.product, *items.product.thumbnail, *items.variant, *items.metadata, +total",
|
|
1006
|
-
},
|
|
1007
|
-
headers,
|
|
1008
|
-
cache: "no-store",
|
|
956
|
+
const options = await getStoreCartClientOptions()
|
|
957
|
+
const res = await medusaCartList(options, {
|
|
958
|
+
fields: "*items, *items.product, *items.product.thumbnail, *items.variant, *items.metadata, +total",
|
|
1009
959
|
}).catch(() => null)
|
|
1010
960
|
|
|
1011
961
|
let buyNowCarts: HttpTypes.StoreCart[] = []
|
|
1012
962
|
let reorderCarts: HttpTypes.StoreCart[] = []
|
|
1013
963
|
|
|
1014
964
|
if (res && res.carts) {
|
|
1015
|
-
// Filter out the main active cart
|
|
1016
965
|
const currentCartId = await getCartId()
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
966
|
+
const carts = res.carts as unknown as HttpTypes.StoreCart[]
|
|
967
|
+
const filteredCarts = carts.filter((c) => c.id !== currentCartId)
|
|
968
|
+
const meta = (c: HttpTypes.StoreCart) =>
|
|
969
|
+
c.metadata as Record<string, unknown> | null | undefined
|
|
970
|
+
|
|
971
|
+
buyNowCarts = filteredCarts.filter((c) => meta(c)?.is_buy_now === true)
|
|
972
|
+
reorderCarts = filteredCarts.filter((c) => meta(c)?.is_reorder === true)
|
|
1021
973
|
}
|
|
1022
974
|
|
|
1023
975
|
return { buyNowCarts, reorderCarts }
|
|
@@ -1036,14 +988,9 @@ export async function resumeAbandonedCart(cartId: string, countryCode: string) {
|
|
|
1036
988
|
}
|
|
1037
989
|
|
|
1038
990
|
export async function deleteCart(cartId: string) {
|
|
1039
|
-
const headers = await getAuthHeaders()
|
|
1040
|
-
|
|
1041
991
|
try {
|
|
1042
|
-
await
|
|
1043
|
-
|
|
1044
|
-
headers,
|
|
1045
|
-
cache: "no-store",
|
|
1046
|
-
})
|
|
992
|
+
const options = await getStoreCartClientOptions()
|
|
993
|
+
await medusaCartDelete(cartId, options)
|
|
1047
994
|
|
|
1048
995
|
revalidateTag("carts")
|
|
1049
996
|
return { success: true }
|