medusa-storefront-data 1.0.0 → 2.0.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 +95 -145
- package/dist/server/dynamic-config.d.ts.map +1 -1
- package/dist/server/dynamic-config.js +5 -2
- 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 +3 -3
- package/dist/server/swaps.d.ts.map +1 -1
- package/dist/server/swaps.js +22 -56
- 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 +140 -189
- package/src/server/dynamic-config.ts +6 -2
- 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 +90 -121
- package/src/server/variants.ts +9 -28
- 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/dist/server/cart.js
CHANGED
|
@@ -3,11 +3,32 @@ import { sdk } from "../config";
|
|
|
3
3
|
import medusaError from "../util/medusa-error";
|
|
4
4
|
import { revalidateTag, revalidatePath } from "next/cache";
|
|
5
5
|
import { redirect } from "next/navigation";
|
|
6
|
+
import { headers as nextHeaders } from "next/headers";
|
|
6
7
|
import { getAuthHeaders, getCacheOptions, getCacheTag, getCartId, removeCartId, setCartId, getHoldCartId, setBuyNowCartId, removeBuyNowCartId, } from "../cookies";
|
|
7
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
|
+
}
|
|
8
18
|
import { getLocale } from "./locale-actions";
|
|
9
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 { getStoreCartClientOptions } from "../util/store-client";
|
|
24
|
+
import { revalidateCartTags } from "../util/revalidate-cart";
|
|
10
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
|
+
}
|
|
11
32
|
/**
|
|
12
33
|
* Retrieves a cart by its ID. If no ID is provided, it will use the cart ID from the cookies.
|
|
13
34
|
* @param cartId - optional - The ID of the cart to retrieve.
|
|
@@ -20,20 +41,16 @@ export const retrieveCart = cache(async (cartId, fields) => {
|
|
|
20
41
|
// If we're not explicitly asking for a specific cartId and we have an active cart
|
|
21
42
|
if (!cartId && id) {
|
|
22
43
|
try {
|
|
23
|
-
const headerList = await
|
|
44
|
+
const headerList = await nextHeaders();
|
|
24
45
|
const pathname = headerList.get("x-pathname") || headerList.get("referer") || "";
|
|
25
46
|
// Skip metadata check if we are clearly in checkout to avoid extra API call
|
|
26
47
|
if (!pathname.includes("/checkout")) {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
method: "GET",
|
|
30
|
-
query: { fields: "metadata" },
|
|
31
|
-
headers: await getAuthHeaders(),
|
|
32
|
-
cache: "no-store",
|
|
33
|
-
})
|
|
48
|
+
const options = await getStoreCartClientOptions();
|
|
49
|
+
const currentCart = await medusaCartRetrieve(id, options, { fields: "metadata" })
|
|
34
50
|
.then(({ cart }) => cart)
|
|
35
51
|
.catch(() => null);
|
|
36
|
-
|
|
52
|
+
const cartMeta = currentCart?.metadata;
|
|
53
|
+
if (cartMeta?.is_buy_now || cartMeta?.is_reorder) {
|
|
37
54
|
await removeBuyNowCartId();
|
|
38
55
|
id = await getCartId(); // Re-fetch ID which will now fall back to the real main cart
|
|
39
56
|
revalidateTag("carts");
|
|
@@ -44,12 +61,11 @@ export const retrieveCart = cache(async (cartId, fields) => {
|
|
|
44
61
|
// Silent fail
|
|
45
62
|
}
|
|
46
63
|
}
|
|
47
|
-
fields ??=
|
|
48
|
-
"*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";
|
|
64
|
+
fields ??= MEDUSA_STORE_CART_DETAIL_FIELDS;
|
|
49
65
|
if (!id) {
|
|
50
66
|
return null;
|
|
51
67
|
}
|
|
52
|
-
const
|
|
68
|
+
const authHeaders = {
|
|
53
69
|
...(await getAuthHeaders()),
|
|
54
70
|
};
|
|
55
71
|
const next = {
|
|
@@ -61,7 +77,7 @@ export const retrieveCart = cache(async (cartId, fields) => {
|
|
|
61
77
|
query: {
|
|
62
78
|
fields,
|
|
63
79
|
},
|
|
64
|
-
headers,
|
|
80
|
+
headers: authHeaders,
|
|
65
81
|
next,
|
|
66
82
|
cache: "no-store",
|
|
67
83
|
})
|
|
@@ -76,19 +92,20 @@ export async function getOrSetCart(countryCode) {
|
|
|
76
92
|
throw new Error(`Region not found for country code: ${countryCode}`);
|
|
77
93
|
}
|
|
78
94
|
let cart = await retrieveCart(undefined, "id,region_id");
|
|
79
|
-
const
|
|
80
|
-
...(await getAuthHeaders()),
|
|
81
|
-
};
|
|
95
|
+
const options = await getStoreCartClientOptions();
|
|
82
96
|
if (!cart) {
|
|
83
97
|
const locale = await getLocale();
|
|
84
|
-
const
|
|
85
|
-
|
|
98
|
+
const { cart: createdCart } = await medusaCartCreate(options, {
|
|
99
|
+
region_id: region.id,
|
|
100
|
+
locale: locale || undefined,
|
|
101
|
+
});
|
|
102
|
+
cart = createdCart;
|
|
86
103
|
await setCartId(cart.id);
|
|
87
104
|
const cartCacheTag = await getCacheTag("carts");
|
|
88
105
|
revalidateTag(cartCacheTag);
|
|
89
106
|
}
|
|
90
107
|
if (cart && cart?.region_id !== region.id) {
|
|
91
|
-
await
|
|
108
|
+
await medusaCartUpdate(cart.id, { region_id: region.id }, options);
|
|
92
109
|
const cartCacheTag = await getCacheTag("carts");
|
|
93
110
|
revalidateTag(cartCacheTag);
|
|
94
111
|
}
|
|
@@ -99,19 +116,15 @@ export async function updateCart(data) {
|
|
|
99
116
|
if (!cartId) {
|
|
100
117
|
throw new Error("No existing cart found, please create one before updating");
|
|
101
118
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.update(cartId, data, {}, headers)
|
|
107
|
-
.then(async ({ cart }) => {
|
|
108
|
-
const cartCacheTag = await getCacheTag("carts");
|
|
109
|
-
revalidateTag(cartCacheTag);
|
|
110
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment");
|
|
111
|
-
revalidateTag(fulfillmentCacheTag);
|
|
119
|
+
try {
|
|
120
|
+
const options = await getStoreCartClientOptions();
|
|
121
|
+
const { cart } = await medusaCartUpdate(cartId, data, options);
|
|
122
|
+
await revalidateCartTags();
|
|
112
123
|
return cart;
|
|
113
|
-
}
|
|
114
|
-
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
throwCartError(e);
|
|
127
|
+
}
|
|
115
128
|
}
|
|
116
129
|
export async function addToCart({ variantId, quantity, countryCode, }) {
|
|
117
130
|
if (!variantId) {
|
|
@@ -121,21 +134,14 @@ export async function addToCart({ variantId, quantity, countryCode, }) {
|
|
|
121
134
|
if (!cart) {
|
|
122
135
|
throw new Error("Error retrieving or creating cart");
|
|
123
136
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
.then(async () => {
|
|
133
|
-
const cartCacheTag = await getCacheTag("carts");
|
|
134
|
-
revalidateTag(cartCacheTag);
|
|
135
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment");
|
|
136
|
-
revalidateTag(fulfillmentCacheTag);
|
|
137
|
-
})
|
|
138
|
-
.catch(medusaError);
|
|
137
|
+
try {
|
|
138
|
+
const options = await getStoreCartClientOptions();
|
|
139
|
+
await medusaCartAddLineItem(cart.id, { variant_id: variantId, quantity }, options);
|
|
140
|
+
await revalidateCartTags();
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
throwCartError(e);
|
|
144
|
+
}
|
|
139
145
|
}
|
|
140
146
|
export async function buyNow({ variantId, quantity, countryCode, }) {
|
|
141
147
|
if (!variantId) {
|
|
@@ -145,36 +151,26 @@ export async function buyNow({ variantId, quantity, countryCode, }) {
|
|
|
145
151
|
if (!region) {
|
|
146
152
|
throw new Error(`Region not found for country code: ${countryCode}`);
|
|
147
153
|
}
|
|
148
|
-
const
|
|
149
|
-
...(await getAuthHeaders()),
|
|
150
|
-
};
|
|
154
|
+
const options = await getStoreCartClientOptions();
|
|
151
155
|
const locale = await getLocale();
|
|
152
156
|
// 1. Create a NEW cart regardless of existing one
|
|
153
|
-
const
|
|
157
|
+
const { cart } = await medusaCartCreate(options, {
|
|
154
158
|
region_id: region.id,
|
|
155
159
|
locale: locale || undefined,
|
|
156
|
-
metadata: { is_buy_now: true }
|
|
157
|
-
}
|
|
158
|
-
const cart = cartResp.cart;
|
|
160
|
+
metadata: { is_buy_now: true },
|
|
161
|
+
});
|
|
159
162
|
// Save the new cart id in "buy_now_cart_id" cookie
|
|
160
163
|
await removeBuyNowCartId();
|
|
161
164
|
await setBuyNowCartId(cart.id);
|
|
162
165
|
// Ensure this new cart is not merged with existing ones
|
|
163
166
|
try {
|
|
164
|
-
await
|
|
165
|
-
method: "POST",
|
|
166
|
-
body: { cart_id: cart.id },
|
|
167
|
-
headers,
|
|
168
|
-
});
|
|
167
|
+
await medusaCartSkipMerge(cart.id, options);
|
|
169
168
|
}
|
|
170
169
|
catch (e) {
|
|
171
170
|
console.error("Failed to skip cart merge for buy now cart:", e);
|
|
172
171
|
}
|
|
173
172
|
// 2. Add the item to this new cart
|
|
174
|
-
await
|
|
175
|
-
variant_id: variantId,
|
|
176
|
-
quantity,
|
|
177
|
-
}, {}, headers);
|
|
173
|
+
await medusaCartAddLineItem(cart.id, { variant_id: variantId, quantity }, options);
|
|
178
174
|
// 3. (REMOVED: No longer overwriting the main cart ID, because getCartId handles buy_now_cart_id priority)
|
|
179
175
|
// 4. OPTIMIZATION: If user is logged in and has addresses, auto-fill and skip to payment
|
|
180
176
|
const customer = await retrieveCustomer().catch(() => null);
|
|
@@ -183,7 +179,7 @@ export async function buyNow({ variantId, quantity, countryCode, }) {
|
|
|
183
179
|
if (defaultAddress) {
|
|
184
180
|
try {
|
|
185
181
|
// Set addresses
|
|
186
|
-
await
|
|
182
|
+
await medusaCartUpdate(cart.id, {
|
|
187
183
|
shipping_address: {
|
|
188
184
|
first_name: defaultAddress.first_name,
|
|
189
185
|
last_name: defaultAddress.last_name,
|
|
@@ -208,16 +204,12 @@ export async function buyNow({ variantId, quantity, countryCode, }) {
|
|
|
208
204
|
phone: defaultAddress.phone,
|
|
209
205
|
company: defaultAddress.company,
|
|
210
206
|
},
|
|
211
|
-
email: customer
|
|
212
|
-
},
|
|
207
|
+
email: customer?.email ?? "",
|
|
208
|
+
}, options);
|
|
213
209
|
// Fetch and set first shipping method
|
|
214
|
-
const { shipping_options } = await
|
|
215
|
-
query: { cart_id: cart.id },
|
|
216
|
-
headers,
|
|
217
|
-
cache: "no-store",
|
|
218
|
-
});
|
|
210
|
+
const { shipping_options } = await medusaShippingOptionsList(cart.id, options);
|
|
219
211
|
if (shipping_options?.length > 0) {
|
|
220
|
-
await
|
|
212
|
+
await medusaCartAddShippingMethod(cart.id, shipping_options[0].id, options);
|
|
221
213
|
skipToPayment = true;
|
|
222
214
|
}
|
|
223
215
|
}
|
|
@@ -245,18 +237,14 @@ export async function updateLineItem({ lineId, quantity, }) {
|
|
|
245
237
|
if (!cartId) {
|
|
246
238
|
throw new Error("Missing cart ID when updating line item");
|
|
247
239
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment");
|
|
257
|
-
revalidateTag(fulfillmentCacheTag);
|
|
258
|
-
})
|
|
259
|
-
.catch(medusaError);
|
|
240
|
+
try {
|
|
241
|
+
const options = await getStoreCartClientOptions();
|
|
242
|
+
await medusaCartUpdateLineItem(cartId, lineId, { quantity }, options);
|
|
243
|
+
await revalidateCartTags();
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
throwCartError(e);
|
|
247
|
+
}
|
|
260
248
|
}
|
|
261
249
|
export async function deleteLineItem(lineId) {
|
|
262
250
|
if (!lineId) {
|
|
@@ -266,18 +254,14 @@ export async function deleteLineItem(lineId) {
|
|
|
266
254
|
if (!cartId) {
|
|
267
255
|
throw new Error("Missing cart ID when deleting line item");
|
|
268
256
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment");
|
|
278
|
-
revalidateTag(fulfillmentCacheTag);
|
|
279
|
-
})
|
|
280
|
-
.catch(medusaError);
|
|
257
|
+
try {
|
|
258
|
+
const options = await getStoreCartClientOptions();
|
|
259
|
+
await medusaCartRemoveLineItem(cartId, lineId, options);
|
|
260
|
+
await revalidateCartTags();
|
|
261
|
+
}
|
|
262
|
+
catch (e) {
|
|
263
|
+
throwCartError(e);
|
|
264
|
+
}
|
|
281
265
|
}
|
|
282
266
|
export async function updateLineItemVariant({ lineId, variantId, quantity, countryCode, }) {
|
|
283
267
|
if (!lineId) {
|
|
@@ -296,26 +280,23 @@ export async function updateLineItemVariant({ lineId, variantId, quantity, count
|
|
|
296
280
|
});
|
|
297
281
|
}
|
|
298
282
|
export async function setShippingMethod({ cartId, shippingMethodId, }) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
return sdk.store.cart
|
|
303
|
-
.addShippingMethod(cartId, { option_id: shippingMethodId }, {}, headers)
|
|
304
|
-
.then(async () => {
|
|
283
|
+
try {
|
|
284
|
+
const options = await getStoreCartClientOptions();
|
|
285
|
+
await medusaCartAddShippingMethod(cartId, shippingMethodId, options);
|
|
305
286
|
const cartCacheTag = await getCacheTag("carts");
|
|
306
287
|
revalidateTag(cartCacheTag);
|
|
307
|
-
}
|
|
308
|
-
|
|
288
|
+
}
|
|
289
|
+
catch (e) {
|
|
290
|
+
throwCartError(e);
|
|
291
|
+
}
|
|
309
292
|
}
|
|
310
293
|
/**
|
|
311
294
|
* Sets a shipping method silently without triggering a full page revalidation.
|
|
312
295
|
*/
|
|
313
296
|
export async function setShippingMethodSilently({ cartId, shippingMethodId, }) {
|
|
314
|
-
const headers = {
|
|
315
|
-
...(await getAuthHeaders()),
|
|
316
|
-
};
|
|
317
297
|
try {
|
|
318
|
-
|
|
298
|
+
const options = await getStoreCartClientOptions();
|
|
299
|
+
await medusaCartAddShippingMethod(cartId, shippingMethodId, options);
|
|
319
300
|
return { success: true };
|
|
320
301
|
}
|
|
321
302
|
catch (e) {
|
|
@@ -323,9 +304,6 @@ export async function setShippingMethodSilently({ cartId, shippingMethodId, }) {
|
|
|
323
304
|
}
|
|
324
305
|
}
|
|
325
306
|
export async function initiatePaymentSession(cart, data) {
|
|
326
|
-
const headers = {
|
|
327
|
-
...(await getAuthHeaders()),
|
|
328
|
-
};
|
|
329
307
|
// 1. RE-FETCH cart with NO CACHE to ensure we have the latest data from the DB
|
|
330
308
|
const latestCart = await retrieveCart(cart.id);
|
|
331
309
|
if (!latestCart)
|
|
@@ -372,12 +350,16 @@ export async function initiatePaymentSession(cart, data) {
|
|
|
372
350
|
addressUpdates.billing_address = cleanAddress(latestCart.billing_address) || cleanAddress(latestCart.shipping_address);
|
|
373
351
|
}
|
|
374
352
|
if (Object.keys(addressUpdates).length > 0) {
|
|
375
|
-
|
|
353
|
+
const options = await getStoreCartClientOptions();
|
|
354
|
+
await medusaCartUpdate(latestCart.id, addressUpdates, options);
|
|
376
355
|
}
|
|
377
356
|
}
|
|
378
|
-
// 3. Final re-fetch (direct
|
|
379
|
-
const
|
|
380
|
-
const
|
|
357
|
+
// 3. Final re-fetch (direct call to bypass any lib-level cache)
|
|
358
|
+
const options = await getStoreCartClientOptions();
|
|
359
|
+
const { cart: finalCartRaw } = await medusaCartRetrieve(cart.id, options, {
|
|
360
|
+
fields: "*shipping_address,*billing_address",
|
|
361
|
+
});
|
|
362
|
+
const finalCart = finalCartRaw;
|
|
381
363
|
// 4. PRE-FLIGHT VALIDATION: Only strictly block for Razorpay, be more lenient for COD
|
|
382
364
|
const isRazorpayProvider = data.provider_id.includes("razorpay");
|
|
383
365
|
const displayPhone = finalCart.shipping_address?.phone || finalCart.billing_address?.phone || phone;
|
|
@@ -401,36 +383,35 @@ export async function initiatePaymentSession(cart, data) {
|
|
|
401
383
|
}
|
|
402
384
|
}
|
|
403
385
|
};
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
+
});
|
|
407
391
|
const cartCacheTag = await getCacheTag("carts");
|
|
408
392
|
revalidateTag(cartCacheTag);
|
|
409
|
-
return
|
|
410
|
-
}
|
|
411
|
-
|
|
393
|
+
return refreshedCart;
|
|
394
|
+
}
|
|
395
|
+
catch (e) {
|
|
412
396
|
const errorMsg = e.message || e.response?.data?.message || "Unknown error";
|
|
413
|
-
|
|
414
|
-
|
|
397
|
+
const label = isRazorpayProvider ? "Razorpay" : "Payment";
|
|
398
|
+
throw new Error(`${label} initialization failed: ${errorMsg}`);
|
|
399
|
+
}
|
|
415
400
|
}
|
|
416
401
|
export async function applyPromotions(codes) {
|
|
417
402
|
const cartId = await getCartId();
|
|
418
403
|
if (!cartId) {
|
|
419
404
|
throw new Error("No existing cart found");
|
|
420
405
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
.update(cartId, { promo_codes: codes }, {}, headers)
|
|
426
|
-
.then(async ({ cart }) => {
|
|
427
|
-
const cartCacheTag = await getCacheTag("carts");
|
|
428
|
-
revalidateTag(cartCacheTag);
|
|
429
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment");
|
|
430
|
-
revalidateTag(fulfillmentCacheTag);
|
|
406
|
+
try {
|
|
407
|
+
const options = await getStoreCartClientOptions();
|
|
408
|
+
const { cart } = await medusaCartApplyPromotions(cartId, codes, options);
|
|
409
|
+
await revalidateCartTags();
|
|
431
410
|
return cart;
|
|
432
|
-
}
|
|
433
|
-
|
|
411
|
+
}
|
|
412
|
+
catch (e) {
|
|
413
|
+
throwCartError(e);
|
|
414
|
+
}
|
|
434
415
|
}
|
|
435
416
|
export async function applyGiftCard(code) {
|
|
436
417
|
// const cartId = getCartId()
|
|
@@ -516,26 +497,24 @@ export async function setAddresses(currentState, formData) {
|
|
|
516
497
|
};
|
|
517
498
|
const data = {
|
|
518
499
|
shipping_address: shippingAddress,
|
|
519
|
-
email: formData.get("email"),
|
|
500
|
+
email: normalizeCartEmail(formData.get("email")),
|
|
520
501
|
};
|
|
502
|
+
if (data.email && !isValidCartEmail(data.email)) {
|
|
503
|
+
throw new Error("Please enter a valid email address.");
|
|
504
|
+
}
|
|
521
505
|
// Save address to customer profile if logged in
|
|
522
506
|
const authHeaders = await getAuthHeaders();
|
|
523
507
|
if (authHeaders && "authorization" in authHeaders) {
|
|
524
508
|
try {
|
|
525
|
-
|
|
526
|
-
const { customer } = await
|
|
527
|
-
method: "GET",
|
|
528
|
-
query: { fields: "*addresses" },
|
|
529
|
-
headers: authHeaders,
|
|
530
|
-
cache: "no-store",
|
|
531
|
-
});
|
|
509
|
+
const options = await getStoreCartClientOptions();
|
|
510
|
+
const { customer } = await medusaCustomerRetrieve(options, { fields: "*addresses" });
|
|
532
511
|
const addressExists = customer?.addresses?.some((a) => a.address_1 === shippingAddress.address_1 &&
|
|
533
512
|
a.postal_code === shippingAddress.postal_code &&
|
|
534
513
|
a.city === shippingAddress.city &&
|
|
535
514
|
a.first_name === shippingAddress.first_name &&
|
|
536
515
|
a.last_name === shippingAddress.last_name);
|
|
537
516
|
if (!addressExists) {
|
|
538
|
-
await
|
|
517
|
+
await medusaCustomerCreateAddress(shippingAddress, options);
|
|
539
518
|
const customerCacheTag = await getCacheTag("customers");
|
|
540
519
|
revalidateTag(customerCacheTag);
|
|
541
520
|
}
|
|
@@ -580,19 +559,19 @@ export async function placeOrder(cartId) {
|
|
|
580
559
|
if (!id) {
|
|
581
560
|
throw new Error("No existing cart found when placing an order");
|
|
582
561
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
.complete(id, {}, headers)
|
|
588
|
-
.then(async (cartRes) => {
|
|
562
|
+
let cartRes;
|
|
563
|
+
try {
|
|
564
|
+
const options = await getStoreCartClientOptions();
|
|
565
|
+
cartRes = await medusaCartComplete(id, options);
|
|
589
566
|
const cartCacheTag = await getCacheTag("carts");
|
|
590
567
|
revalidateTag(cartCacheTag);
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
568
|
+
}
|
|
569
|
+
catch (e) {
|
|
570
|
+
throwCartError(e);
|
|
571
|
+
}
|
|
594
572
|
if (cartRes?.type === "order") {
|
|
595
|
-
const
|
|
573
|
+
const order = cartRes.order;
|
|
574
|
+
const countryCode = order.shipping_address?.country_code?.toLowerCase();
|
|
596
575
|
const orderCacheTag = await getCacheTag("orders");
|
|
597
576
|
revalidateTag(orderCacheTag);
|
|
598
577
|
// NEW LOGIC: Check if we just completed a Buy Now cart
|
|
@@ -608,7 +587,7 @@ export async function placeOrder(cartId) {
|
|
|
608
587
|
// Regular checkout: clear the main cart
|
|
609
588
|
await removeCartId();
|
|
610
589
|
}
|
|
611
|
-
redirect(`/${countryCode}/order/${
|
|
590
|
+
redirect(`/${countryCode}/order/${order.id}/confirmed`);
|
|
612
591
|
}
|
|
613
592
|
return cartRes.cart;
|
|
614
593
|
}
|
|
@@ -651,9 +630,6 @@ export async function listCartOptions() {
|
|
|
651
630
|
}
|
|
652
631
|
export async function addCustomerAddressToCart(currentState, formData) {
|
|
653
632
|
try {
|
|
654
|
-
const headers = {
|
|
655
|
-
...(await getAuthHeaders()),
|
|
656
|
-
};
|
|
657
633
|
const shippingCountryCode = formData.get("shipping_address.country_code")?.toLowerCase() || "in";
|
|
658
634
|
// Parse address data from formData (which uses shipping_address. prefix)
|
|
659
635
|
const addressData = {
|
|
@@ -676,11 +652,12 @@ export async function addCustomerAddressToCart(currentState, formData) {
|
|
|
676
652
|
// 1. Add/Update Customer Address Book
|
|
677
653
|
// We try/catch this separately so if it fails (e.g. user not logged in), we still try to proceed with checkout
|
|
678
654
|
try {
|
|
655
|
+
const options = await getStoreCartClientOptions();
|
|
679
656
|
if (addressId) {
|
|
680
|
-
await
|
|
657
|
+
await medusaCustomerUpdateAddress(addressId, addressData, options);
|
|
681
658
|
}
|
|
682
659
|
else {
|
|
683
|
-
await
|
|
660
|
+
await medusaCustomerCreateAddress(addressData, options);
|
|
684
661
|
}
|
|
685
662
|
const customerCacheTag = await getCacheTag("customers");
|
|
686
663
|
revalidateTag(customerCacheTag);
|
|
@@ -707,8 +684,11 @@ export async function addCustomerAddressToCart(currentState, formData) {
|
|
|
707
684
|
country_code: addressData.country_code,
|
|
708
685
|
phone: addressData.phone,
|
|
709
686
|
},
|
|
710
|
-
email: formData.get("email"),
|
|
687
|
+
email: normalizeCartEmail(formData.get("email")),
|
|
711
688
|
};
|
|
689
|
+
if (cartData.email && !isValidCartEmail(cartData.email)) {
|
|
690
|
+
throw new Error("Please enter a valid email address.");
|
|
691
|
+
}
|
|
712
692
|
const sameAsBilling = formData.get("same_as_billing");
|
|
713
693
|
if (sameAsBilling === "on") {
|
|
714
694
|
cartData.billing_address = cartData.shipping_address;
|
|
@@ -735,15 +715,17 @@ export async function updateAddressSilently(data) {
|
|
|
735
715
|
if (!cartId)
|
|
736
716
|
return;
|
|
737
717
|
try {
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
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 getStoreCartClientOptions();
|
|
726
|
+
await medusaCartUpdate(cartId, payload, options);
|
|
742
727
|
// Revalidate tags to ensure CartTotals gets new shipping info
|
|
743
|
-
|
|
744
|
-
revalidateTag(cartCacheTag);
|
|
745
|
-
const fulfillmentCacheTag = await getCacheTag("fulfillment");
|
|
746
|
-
revalidateTag(fulfillmentCacheTag);
|
|
728
|
+
await revalidateCartTags();
|
|
747
729
|
return { success: true };
|
|
748
730
|
}
|
|
749
731
|
catch (e) {
|
|
@@ -758,10 +740,8 @@ export async function updateCartMetadataSilently(metadata) {
|
|
|
758
740
|
if (!cartId)
|
|
759
741
|
return;
|
|
760
742
|
try {
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
};
|
|
764
|
-
await sdk.store.cart.update(cartId, { metadata }, {}, headers);
|
|
743
|
+
const options = await getStoreCartClientOptions();
|
|
744
|
+
await medusaCartUpdate(cartId, { metadata }, options);
|
|
765
745
|
// We intentionally DO NOT call revalidateTag here to prevent page refresh loops
|
|
766
746
|
return { success: true };
|
|
767
747
|
}
|
|
@@ -770,31 +750,25 @@ export async function updateCartMetadataSilently(metadata) {
|
|
|
770
750
|
}
|
|
771
751
|
}
|
|
772
752
|
export async function getAbandonedCarts() {
|
|
773
|
-
const
|
|
774
|
-
...(await getAuthHeaders()),
|
|
775
|
-
};
|
|
753
|
+
const authHeaders = await getAuthHeaders();
|
|
776
754
|
// If no authorization, return empty arrays
|
|
777
|
-
if (!
|
|
755
|
+
if (!("authorization" in authHeaders)) {
|
|
778
756
|
return { buyNowCarts: [], reorderCarts: [] };
|
|
779
757
|
}
|
|
780
758
|
try {
|
|
781
|
-
|
|
782
|
-
const res = await
|
|
783
|
-
|
|
784
|
-
query: {
|
|
785
|
-
fields: "*items, *items.product, *items.product.thumbnail, *items.variant, *items.metadata, +total",
|
|
786
|
-
},
|
|
787
|
-
headers,
|
|
788
|
-
cache: "no-store",
|
|
759
|
+
const options = await getStoreCartClientOptions();
|
|
760
|
+
const res = await medusaCartList(options, {
|
|
761
|
+
fields: "*items, *items.product, *items.product.thumbnail, *items.variant, *items.metadata, +total",
|
|
789
762
|
}).catch(() => null);
|
|
790
763
|
let buyNowCarts = [];
|
|
791
764
|
let reorderCarts = [];
|
|
792
765
|
if (res && res.carts) {
|
|
793
|
-
// Filter out the main active cart
|
|
794
766
|
const currentCartId = await getCartId();
|
|
795
|
-
const
|
|
796
|
-
|
|
797
|
-
|
|
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);
|
|
798
772
|
}
|
|
799
773
|
return { buyNowCarts, reorderCarts };
|
|
800
774
|
}
|
|
@@ -810,13 +784,9 @@ export async function resumeAbandonedCart(cartId, countryCode) {
|
|
|
810
784
|
redirect(`/${countryCode}/checkout?cart_id=${cartId}`);
|
|
811
785
|
}
|
|
812
786
|
export async function deleteCart(cartId) {
|
|
813
|
-
const headers = await getAuthHeaders();
|
|
814
787
|
try {
|
|
815
|
-
await
|
|
816
|
-
|
|
817
|
-
headers,
|
|
818
|
-
cache: "no-store",
|
|
819
|
-
});
|
|
788
|
+
const options = await getStoreCartClientOptions();
|
|
789
|
+
await medusaCartDelete(cartId, options);
|
|
820
790
|
revalidateTag("carts");
|
|
821
791
|
return { success: true };
|
|
822
792
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const
|
|
1
|
+
import { HttpTypes } from "@medusajs/types";
|
|
2
|
+
export declare const listCategories: (query?: Record<string, any>) => Promise<HttpTypes.StoreProductCategory[]>;
|
|
3
|
+
export declare const getCategoryByHandle: (categoryHandle: string[]) => Promise<HttpTypes.StoreProductCategory | null>;
|
|
3
4
|
//# sourceMappingURL=categories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../src/server/categories.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../src/server/categories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAI3C,eAAO,MAAM,cAAc,GAAU,QAAQ,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,8CAW/D,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAU,gBAAgB,MAAM,EAAE,mDAuBjE,CAAA"}
|