medusa-storefront-data 1.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/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +31 -0
- package/dist/cookies.d.ts +23 -0
- package/dist/cookies.d.ts.map +1 -0
- package/dist/cookies.js +140 -0
- package/dist/server/cart.d.ts +92 -0
- package/dist/server/cart.d.ts.map +1 -0
- package/dist/server/cart.js +827 -0
- package/dist/server/categories.d.ts +3 -0
- package/dist/server/categories.d.ts.map +1 -0
- package/dist/server/categories.js +71 -0
- package/dist/server/collections.d.ts +8 -0
- package/dist/server/collections.d.ts.map +1 -0
- package/dist/server/collections.js +84 -0
- package/dist/server/customer-registration.d.ts +142 -0
- package/dist/server/customer-registration.d.ts.map +1 -0
- package/dist/server/customer-registration.js +295 -0
- package/dist/server/customer.d.ts +48 -0
- package/dist/server/customer.d.ts.map +1 -0
- package/dist/server/customer.js +462 -0
- package/dist/server/dynamic-config.d.ts +125 -0
- package/dist/server/dynamic-config.d.ts.map +1 -0
- package/dist/server/dynamic-config.js +263 -0
- package/dist/server/fulfillment.d.ts +4 -0
- package/dist/server/fulfillment.d.ts.map +1 -0
- package/dist/server/fulfillment.js +72 -0
- package/dist/server/guest.d.ts +109 -0
- package/dist/server/guest.d.ts.map +1 -0
- package/dist/server/guest.js +304 -0
- package/dist/server/index.d.ts +21 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +20 -0
- package/dist/server/locale-actions.d.ts +14 -0
- package/dist/server/locale-actions.d.ts.map +1 -0
- package/dist/server/locale-actions.js +63 -0
- package/dist/server/locales.d.ts +10 -0
- package/dist/server/locales.d.ts.map +1 -0
- package/dist/server/locales.js +20 -0
- package/dist/server/notifications.d.ts +2 -0
- package/dist/server/notifications.d.ts.map +1 -0
- package/dist/server/notifications.js +20 -0
- package/dist/server/onboarding.d.ts +2 -0
- package/dist/server/onboarding.d.ts.map +1 -0
- package/dist/server/onboarding.js +8 -0
- package/dist/server/orders.d.ts +69 -0
- package/dist/server/orders.d.ts.map +1 -0
- package/dist/server/orders.js +371 -0
- package/dist/server/payment-details.d.ts +5 -0
- package/dist/server/payment-details.d.ts.map +1 -0
- package/dist/server/payment-details.js +53 -0
- package/dist/server/payment.d.ts +2 -0
- package/dist/server/payment.d.ts.map +1 -0
- package/dist/server/payment.js +25 -0
- package/dist/server/products.d.ts +58 -0
- package/dist/server/products.d.ts.map +1 -0
- package/dist/server/products.js +285 -0
- package/dist/server/regions.d.ts +5 -0
- package/dist/server/regions.d.ts.map +1 -0
- package/dist/server/regions.js +54 -0
- package/dist/server/returns.d.ts +29 -0
- package/dist/server/returns.d.ts.map +1 -0
- package/dist/server/returns.js +236 -0
- package/dist/server/swaps.d.ts +14 -0
- package/dist/server/swaps.d.ts.map +1 -0
- package/dist/server/swaps.js +123 -0
- package/dist/server/variants.d.ts +3 -0
- package/dist/server/variants.d.ts.map +1 -0
- package/dist/server/variants.js +26 -0
- package/dist/util/get-locale-header.d.ts +4 -0
- package/dist/util/get-locale-header.d.ts.map +1 -0
- package/dist/util/get-locale-header.js +7 -0
- package/dist/util/medusa-error.d.ts +2 -0
- package/dist/util/medusa-error.d.ts.map +1 -0
- package/dist/util/medusa-error.js +18 -0
- package/package.json +152 -0
- package/src/config.ts +39 -0
- package/src/cookies.ts +171 -0
- package/src/middleware.ts +2 -0
- package/src/server/cart.ts +1054 -0
- package/src/server/categories.ts +94 -0
- package/src/server/collections.ts +113 -0
- package/src/server/customer-registration.ts +349 -0
- package/src/server/customer.ts +581 -0
- package/src/server/dynamic-config.ts +403 -0
- package/src/server/fulfillment.ts +97 -0
- package/src/server/guest.ts +333 -0
- package/src/server/index.ts +21 -0
- package/src/server/locale-actions.ts +74 -0
- package/src/server/locales.ts +28 -0
- package/src/server/notifications.ts +22 -0
- package/src/server/onboarding.ts +9 -0
- package/src/server/orders.ts +467 -0
- package/src/server/payment-details.ts +69 -0
- package/src/server/payment.ts +35 -0
- package/src/server/products.ts +378 -0
- package/src/server/regions.ts +66 -0
- package/src/server/returns.ts +294 -0
- package/src/server/swaps.ts +150 -0
- package/src/server/variants.ts +38 -0
- package/src/server/wishlist.ts +64 -0
- package/src/services/middleware.ts +54 -0
- package/src/util/get-locale-header.ts +8 -0
- package/src/util/medusa-error.ts +19 -0
- package/src/util/sort-products.ts +47 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { sdk } from "../config";
|
|
3
|
+
import medusaError from "../util/medusa-error";
|
|
4
|
+
import { revalidateTag } from "next/cache";
|
|
5
|
+
import { redirect } from "next/navigation";
|
|
6
|
+
import { cookies } from "next/headers";
|
|
7
|
+
import { getAuthHeaders, getCacheTag, getCartId, removeAuthToken, removeCartId, removeSyncLock, setAuthToken, setCartId, } from "../cookies";
|
|
8
|
+
import { cache } from "react";
|
|
9
|
+
export const retrieveCustomer = cache(async () => {
|
|
10
|
+
const authHeaders = await getAuthHeaders();
|
|
11
|
+
if (!authHeaders)
|
|
12
|
+
return null;
|
|
13
|
+
const headers = {
|
|
14
|
+
...authHeaders,
|
|
15
|
+
};
|
|
16
|
+
try {
|
|
17
|
+
const { customer } = await sdk.client.fetch(`/store/customers/me`, {
|
|
18
|
+
method: "GET",
|
|
19
|
+
query: { fields: "*addresses" },
|
|
20
|
+
headers: headers,
|
|
21
|
+
cache: "no-store",
|
|
22
|
+
});
|
|
23
|
+
return customer;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const errStr = error.toString().toLowerCase();
|
|
27
|
+
// If the error indicates a pending deletion, return a special object
|
|
28
|
+
if (errStr.includes("active account deletion request") ||
|
|
29
|
+
(error.message && error.message.toLowerCase().includes("active account deletion request"))) {
|
|
30
|
+
const cookieStore = await cookies();
|
|
31
|
+
const cookieEmail = cookieStore.get("_medusa_customer_email")?.value;
|
|
32
|
+
return { id: "pending_deletion", email: cookieEmail || "pending" };
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
export const updateCustomer = async (body) => {
|
|
38
|
+
const headers = {
|
|
39
|
+
...(await getAuthHeaders()),
|
|
40
|
+
};
|
|
41
|
+
const updateRes = await sdk.store.customer
|
|
42
|
+
.update(body, {}, headers)
|
|
43
|
+
.then(({ customer }) => customer)
|
|
44
|
+
.catch(medusaError);
|
|
45
|
+
const cacheTag = await getCacheTag("customers");
|
|
46
|
+
revalidateTag(cacheTag);
|
|
47
|
+
return updateRes;
|
|
48
|
+
};
|
|
49
|
+
export async function signup(_currentState, formData) {
|
|
50
|
+
const password = formData.get("password");
|
|
51
|
+
const customerForm = {
|
|
52
|
+
email: formData.get("email"),
|
|
53
|
+
first_name: formData.get("first_name"),
|
|
54
|
+
last_name: formData.get("last_name"),
|
|
55
|
+
phone: formData.get("phone")?.replace(/[^\d+]/g, ""),
|
|
56
|
+
};
|
|
57
|
+
try {
|
|
58
|
+
const token = await sdk.auth.register("customer", "emailpass", {
|
|
59
|
+
email: customerForm.email,
|
|
60
|
+
password: password,
|
|
61
|
+
});
|
|
62
|
+
await setAuthToken(token);
|
|
63
|
+
const headers = {
|
|
64
|
+
...(await getAuthHeaders()),
|
|
65
|
+
};
|
|
66
|
+
const { customer: createdCustomer } = await sdk.store.customer.create(customerForm, {}, headers);
|
|
67
|
+
const loginToken = await sdk.auth.login("customer", "emailpass", {
|
|
68
|
+
email: customerForm.email,
|
|
69
|
+
password,
|
|
70
|
+
});
|
|
71
|
+
await setAuthToken(loginToken);
|
|
72
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
73
|
+
revalidateTag(customerCacheTag);
|
|
74
|
+
await transferCart(loginToken);
|
|
75
|
+
return createdCustomer;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return error.toString();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function login(_currentState, formData) {
|
|
82
|
+
let email = formData.get("email_or_phone");
|
|
83
|
+
const password = formData.get("password");
|
|
84
|
+
// Sanitize phone number: remove spaces, dashes, etc if it looks like a phone number
|
|
85
|
+
// If it doesn't have '@', we treat it as a potential phone number and clean it
|
|
86
|
+
if (email && !email.includes("@")) {
|
|
87
|
+
email = email.replace(/[^\d+]/g, "");
|
|
88
|
+
}
|
|
89
|
+
let shouldRedirect = false;
|
|
90
|
+
let countryCode = "in";
|
|
91
|
+
try {
|
|
92
|
+
const token = await sdk.auth.login("customer", "emailpass", { email_or_phone: email, password });
|
|
93
|
+
await setAuthToken(token);
|
|
94
|
+
// Store email in cookie for deletion flow (needed for cancellation modal)
|
|
95
|
+
const cookieStore = await cookies();
|
|
96
|
+
cookieStore.set("_medusa_customer_email", email, { maxAge: 60 * 60 * 24 * 7, path: "/" });
|
|
97
|
+
// Force a check to see if we are blocked
|
|
98
|
+
try {
|
|
99
|
+
await sdk.store.customer.retrieve({}, {
|
|
100
|
+
authorization: `Bearer ${token}`
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const errStr = err.toString().toLowerCase();
|
|
105
|
+
if (errStr.includes("active account deletion request")) {
|
|
106
|
+
return "ACCOUNT_DELETION_PENDING";
|
|
107
|
+
}
|
|
108
|
+
// If it's another error, we might still want to know, but deletion is our priority
|
|
109
|
+
throw err;
|
|
110
|
+
}
|
|
111
|
+
// Transfer cart after login success - Moved here to ensure execution
|
|
112
|
+
try {
|
|
113
|
+
await transferCart(token);
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
console.error("Transfer cart failed in login:", e);
|
|
117
|
+
}
|
|
118
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
119
|
+
revalidateTag(customerCacheTag);
|
|
120
|
+
countryCode = formData.get("country_code") || "in";
|
|
121
|
+
shouldRedirect = true;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const errorStr = error.toString().toLowerCase();
|
|
125
|
+
if (errorStr.includes("active account deletion request") ||
|
|
126
|
+
(error.message && error.message.toLowerCase().includes("active account deletion request"))) {
|
|
127
|
+
// Still set email cookie even if blocked
|
|
128
|
+
const cookieStore = await cookies();
|
|
129
|
+
cookieStore.set("_medusa_customer_email", email, { maxAge: 60 * 60 * 24 * 7, path: "/" });
|
|
130
|
+
return "ACCOUNT_DELETION_PENDING";
|
|
131
|
+
}
|
|
132
|
+
if (errorStr.includes("invalid") || errorStr.includes("401") || errorStr.includes("not found")) {
|
|
133
|
+
return "Invalid credentials. Please try again.";
|
|
134
|
+
}
|
|
135
|
+
return error.message || error.toString();
|
|
136
|
+
}
|
|
137
|
+
if (shouldRedirect) {
|
|
138
|
+
const redirectUrl = formData.get("redirect_url");
|
|
139
|
+
// Check if it's a "keep-me-here" context (Wishlist or Review Popups)
|
|
140
|
+
const hasKeepContext = redirectUrl?.includes("login_context=keep");
|
|
141
|
+
// Security + Context check
|
|
142
|
+
if (redirectUrl && redirectUrl.startsWith("/") && hasKeepContext) {
|
|
143
|
+
redirect(redirectUrl);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// DEFAULT: Always Home Page
|
|
147
|
+
redirect(`/${countryCode}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
export async function signout(countryCode) {
|
|
152
|
+
await sdk.auth.logout();
|
|
153
|
+
await removeAuthToken();
|
|
154
|
+
await removeCartId();
|
|
155
|
+
await removeSyncLock();
|
|
156
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
157
|
+
revalidateTag(customerCacheTag);
|
|
158
|
+
await removeCartId();
|
|
159
|
+
const cartCacheTag = await getCacheTag("carts");
|
|
160
|
+
revalidateTag(cartCacheTag);
|
|
161
|
+
redirect(`/${countryCode}`);
|
|
162
|
+
}
|
|
163
|
+
export async function transferCart(token) {
|
|
164
|
+
const cartId = await getCartId();
|
|
165
|
+
const authHeaders = token
|
|
166
|
+
? { authorization: `Bearer ${token}` }
|
|
167
|
+
: await getAuthHeaders();
|
|
168
|
+
console.log("--- TransferCart Debug ---");
|
|
169
|
+
console.log("Token provided:", !!token);
|
|
170
|
+
console.log("Guest Cart ID:", cartId);
|
|
171
|
+
const publishableKey = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY;
|
|
172
|
+
const backendUrl = process.env.MEDUSA_BACKEND_URL || process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL || "http://localhost:9000";
|
|
173
|
+
try {
|
|
174
|
+
console.log("Calling merge API (always)...");
|
|
175
|
+
const response = await fetch(`${backendUrl}/store/carts/merge`, {
|
|
176
|
+
method: "POST",
|
|
177
|
+
headers: {
|
|
178
|
+
"Content-Type": "application/json",
|
|
179
|
+
"x-publishable-api-key": publishableKey || "",
|
|
180
|
+
...authHeaders,
|
|
181
|
+
},
|
|
182
|
+
// Only include body if cartId exists
|
|
183
|
+
...(cartId ? { body: JSON.stringify({ cart_id: cartId }) } : {}),
|
|
184
|
+
cache: "no-store",
|
|
185
|
+
});
|
|
186
|
+
if (response.ok) {
|
|
187
|
+
const data = await response.json();
|
|
188
|
+
console.log("--- Login Merge Response (JSON) ---");
|
|
189
|
+
console.log(JSON.stringify(data, null, 2));
|
|
190
|
+
console.log("-----------------------------------");
|
|
191
|
+
const activeCartId = data.cart?.id || data.id || data.cart_id;
|
|
192
|
+
if (activeCartId) {
|
|
193
|
+
console.log("Storing Cart ID in cookie:", activeCartId);
|
|
194
|
+
await setCartId(activeCartId);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else if (response.status === 404) {
|
|
198
|
+
// 404 is fine - it just means the customer has no active cart yet
|
|
199
|
+
console.log("No active cart found for this customer (expected).");
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const errorText = await response.text();
|
|
203
|
+
console.log(`Merge API Info (${response.status}):`, errorText);
|
|
204
|
+
if (cartId) {
|
|
205
|
+
await sdk.store.cart.transferCart(cartId, {}, authHeaders).catch(() => { });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error("Merge API error:", error.message);
|
|
211
|
+
if (cartId) {
|
|
212
|
+
await sdk.store.cart.transferCart(cartId, {}, authHeaders).catch(() => { });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
console.log("--------------------------");
|
|
216
|
+
const cartCacheTag = await getCacheTag("carts");
|
|
217
|
+
revalidateTag(cartCacheTag);
|
|
218
|
+
}
|
|
219
|
+
export const addCustomerAddress = async (currentState, formData) => {
|
|
220
|
+
const isDefaultBilling = currentState.isDefaultBilling || false;
|
|
221
|
+
const isDefaultShipping = currentState.isDefaultShipping || false;
|
|
222
|
+
const address = {
|
|
223
|
+
first_name: formData.get("first_name"),
|
|
224
|
+
last_name: formData.get("last_name"),
|
|
225
|
+
company: formData.get("company"),
|
|
226
|
+
address_1: formData.get("address_1"),
|
|
227
|
+
address_2: formData.get("address_2"),
|
|
228
|
+
city: formData.get("city"),
|
|
229
|
+
postal_code: formData.get("postal_code"),
|
|
230
|
+
province: formData.get("province"),
|
|
231
|
+
country_code: formData.get("country_code"),
|
|
232
|
+
phone: formData.get("phone"),
|
|
233
|
+
is_default_billing: isDefaultBilling,
|
|
234
|
+
is_default_shipping: isDefaultShipping,
|
|
235
|
+
metadata: {
|
|
236
|
+
address_type: formData.get("address_type") || "HOME",
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const headers = {
|
|
240
|
+
...(await getAuthHeaders()),
|
|
241
|
+
};
|
|
242
|
+
return sdk.store.customer
|
|
243
|
+
.createAddress(address, {}, headers)
|
|
244
|
+
.then(async ({ customer }) => {
|
|
245
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
246
|
+
revalidateTag(customerCacheTag);
|
|
247
|
+
return { success: true, error: null };
|
|
248
|
+
})
|
|
249
|
+
.catch((err) => {
|
|
250
|
+
return { success: false, error: err.toString() };
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
export const deleteCustomerAddress = async (addressId) => {
|
|
254
|
+
const headers = {
|
|
255
|
+
...(await getAuthHeaders()),
|
|
256
|
+
};
|
|
257
|
+
await sdk.store.customer
|
|
258
|
+
.deleteAddress(addressId, headers)
|
|
259
|
+
.then(async () => {
|
|
260
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
261
|
+
revalidateTag(customerCacheTag);
|
|
262
|
+
return { success: true, error: null };
|
|
263
|
+
})
|
|
264
|
+
.catch((err) => {
|
|
265
|
+
return { success: false, error: err.toString() };
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
export const updateCustomerAddress = async (currentState, formData) => {
|
|
269
|
+
const addressId = currentState.addressId || formData.get("addressId");
|
|
270
|
+
if (!addressId) {
|
|
271
|
+
return { success: false, error: "Address ID is required" };
|
|
272
|
+
}
|
|
273
|
+
const address = {
|
|
274
|
+
first_name: formData.get("first_name"),
|
|
275
|
+
last_name: formData.get("last_name"),
|
|
276
|
+
company: formData.get("company"),
|
|
277
|
+
address_1: formData.get("address_1"),
|
|
278
|
+
address_2: formData.get("address_2"),
|
|
279
|
+
city: formData.get("city"),
|
|
280
|
+
postal_code: formData.get("postal_code"),
|
|
281
|
+
province: formData.get("province"),
|
|
282
|
+
country_code: formData.get("country_code"),
|
|
283
|
+
metadata: {
|
|
284
|
+
address_type: formData.get("address_type") || "HOME",
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
const phone = formData.get("phone");
|
|
288
|
+
if (phone) {
|
|
289
|
+
address.phone = phone;
|
|
290
|
+
}
|
|
291
|
+
const headers = {
|
|
292
|
+
...(await getAuthHeaders()),
|
|
293
|
+
};
|
|
294
|
+
return sdk.store.customer
|
|
295
|
+
.updateAddress(addressId, address, {}, headers)
|
|
296
|
+
.then(async () => {
|
|
297
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
298
|
+
revalidateTag(customerCacheTag);
|
|
299
|
+
return { success: true, error: null };
|
|
300
|
+
})
|
|
301
|
+
.catch((err) => {
|
|
302
|
+
return { success: false, error: err.toString() };
|
|
303
|
+
});
|
|
304
|
+
};
|
|
305
|
+
export const setDefaultAddress = async (addressId) => {
|
|
306
|
+
const headers = {
|
|
307
|
+
...(await getAuthHeaders()),
|
|
308
|
+
};
|
|
309
|
+
return sdk.store.customer
|
|
310
|
+
.updateAddress(addressId, { is_default_shipping: true }, {}, headers)
|
|
311
|
+
.then(async () => {
|
|
312
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
313
|
+
revalidateTag(customerCacheTag);
|
|
314
|
+
return { success: true, error: null };
|
|
315
|
+
})
|
|
316
|
+
.catch((err) => {
|
|
317
|
+
return { success: false, error: err.toString() };
|
|
318
|
+
});
|
|
319
|
+
};
|
|
320
|
+
export async function initiateGoogleAuth() {
|
|
321
|
+
try {
|
|
322
|
+
const backendUrl = process.env.MEDUSA_BACKEND_URL || process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL;
|
|
323
|
+
if (!backendUrl) {
|
|
324
|
+
return { error: "Backend URL not configured" };
|
|
325
|
+
}
|
|
326
|
+
const response = await fetch(`${backendUrl}/auth/customer/google`, {
|
|
327
|
+
method: "POST",
|
|
328
|
+
headers: {
|
|
329
|
+
"Content-Type": "application/json",
|
|
330
|
+
},
|
|
331
|
+
cache: "no-store",
|
|
332
|
+
});
|
|
333
|
+
if (!response.ok) {
|
|
334
|
+
return { error: "Google auth failed" };
|
|
335
|
+
}
|
|
336
|
+
const result = await response.json();
|
|
337
|
+
let redirectUrl = typeof result === "string" ? result : result?.location;
|
|
338
|
+
if (!redirectUrl) {
|
|
339
|
+
return { error: "No redirect URL received from Google OAuth" };
|
|
340
|
+
}
|
|
341
|
+
// Fix redirect URL: Remove country code prefix from callback URL if present
|
|
342
|
+
// Example: https://chocomelon.in/in/auth/customer/google/callback -> https://chocomelon.in/auth/customer/google/callback
|
|
343
|
+
try {
|
|
344
|
+
const url = new URL(redirectUrl);
|
|
345
|
+
const pathParts = url.pathname.split('/').filter(Boolean);
|
|
346
|
+
// Check if path starts with country code pattern (2-3 letter code)
|
|
347
|
+
if (pathParts.length > 0 && /^[a-z]{2,3}$/i.test(pathParts[0])) {
|
|
348
|
+
// Check if next part is 'auth'
|
|
349
|
+
if (pathParts.length > 1 && pathParts[1] === 'auth') {
|
|
350
|
+
// Remove country code from path
|
|
351
|
+
pathParts.shift();
|
|
352
|
+
url.pathname = '/' + pathParts.join('/');
|
|
353
|
+
redirectUrl = url.toString();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
catch (e) {
|
|
358
|
+
// If URL parsing fails, use original redirectUrl
|
|
359
|
+
}
|
|
360
|
+
return { redirectUrl };
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
return { error: error.message || "Internal server error" };
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
export async function handleGoogleAuthCallback(params) {
|
|
367
|
+
try {
|
|
368
|
+
if (!params.code || !params.state) {
|
|
369
|
+
return { error: "Missing authentication parameters" };
|
|
370
|
+
}
|
|
371
|
+
const backendUrl = process.env.MEDUSA_BACKEND_URL || process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL;
|
|
372
|
+
if (!backendUrl) {
|
|
373
|
+
return { error: "Backend URL not configured" };
|
|
374
|
+
}
|
|
375
|
+
const response = await fetch(`${backendUrl}/auth/customer/google/callback?${new URLSearchParams(params).toString()}`, {
|
|
376
|
+
method: "GET",
|
|
377
|
+
headers: {
|
|
378
|
+
"Content-Type": "application/json",
|
|
379
|
+
},
|
|
380
|
+
cache: "no-store",
|
|
381
|
+
});
|
|
382
|
+
if (!response.ok) {
|
|
383
|
+
return { error: `Authentication failed: ${response.status} - ${response.statusText}` };
|
|
384
|
+
}
|
|
385
|
+
const data = await response.json();
|
|
386
|
+
const token = data.token || data;
|
|
387
|
+
if (!token || typeof token !== "string") {
|
|
388
|
+
return { error: "No token received" };
|
|
389
|
+
}
|
|
390
|
+
return { token };
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
return { error: error.message || "Internal server error" };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
export async function handleGoogleCallback(token, email, first_name, last_name) {
|
|
397
|
+
try {
|
|
398
|
+
if (!token || typeof token !== "string") {
|
|
399
|
+
return { error: "Token is required" };
|
|
400
|
+
}
|
|
401
|
+
await setAuthToken(token);
|
|
402
|
+
await transferCart(token).catch(() => { });
|
|
403
|
+
if (email && typeof email === "string") {
|
|
404
|
+
const cookieStore = await cookies();
|
|
405
|
+
cookieStore.set("_medusa_customer_email", email, { maxAge: 60 * 60 * 24 * 7, path: "/" });
|
|
406
|
+
const headers = await getAuthHeaders();
|
|
407
|
+
if (headers && "authorization" in headers) {
|
|
408
|
+
try {
|
|
409
|
+
await sdk.store.customer.create({ email, ...(first_name && { first_name }), ...(last_name && { last_name }) }, {}, headers);
|
|
410
|
+
}
|
|
411
|
+
catch (err) {
|
|
412
|
+
if (!err.message?.includes("already exists") && !err.message?.includes("duplicate")) {
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
418
|
+
if (customerCacheTag)
|
|
419
|
+
revalidateTag(customerCacheTag);
|
|
420
|
+
return { success: true };
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
return { error: error.message || "Internal server error" };
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
export async function uploadProfileImage(formData) {
|
|
427
|
+
try {
|
|
428
|
+
const imageFile = formData.get("image");
|
|
429
|
+
if (!imageFile) {
|
|
430
|
+
return { error: "No image file provided" };
|
|
431
|
+
}
|
|
432
|
+
// Create new FormData with 'files' field as expected by the backend
|
|
433
|
+
const uploadFormData = new FormData();
|
|
434
|
+
uploadFormData.append("files", imageFile);
|
|
435
|
+
const { uploadStoreFiles } = await import("medusa-reviews-logic/server");
|
|
436
|
+
const uploadResult = await uploadStoreFiles(uploadFormData);
|
|
437
|
+
if (!uploadResult.success) {
|
|
438
|
+
return { error: uploadResult.error };
|
|
439
|
+
}
|
|
440
|
+
const imageUrl = uploadResult.files?.[0]?.url;
|
|
441
|
+
if (!imageUrl) {
|
|
442
|
+
throw new Error("No image URL returned from server");
|
|
443
|
+
}
|
|
444
|
+
// Fetch current customer to preserve existing metadata
|
|
445
|
+
const currentCustomer = await retrieveCustomer();
|
|
446
|
+
const existingMetadata = currentCustomer?.metadata || {};
|
|
447
|
+
const newMetadata = {
|
|
448
|
+
...existingMetadata,
|
|
449
|
+
profile_image_url: imageUrl,
|
|
450
|
+
};
|
|
451
|
+
// Update customer metadata
|
|
452
|
+
await updateCustomer({ metadata: newMetadata });
|
|
453
|
+
const customerCacheTag = await getCacheTag("customers");
|
|
454
|
+
if (customerCacheTag) {
|
|
455
|
+
revalidateTag(customerCacheTag);
|
|
456
|
+
}
|
|
457
|
+
return { success: true, imageUrl };
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
return { error: error.message || "Failed to upload image" };
|
|
461
|
+
}
|
|
462
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
export interface DynamicConfig {
|
|
2
|
+
"homepage-config"?: {
|
|
3
|
+
logo?: string;
|
|
4
|
+
"homepage-banner-array"?: Array<{
|
|
5
|
+
"homepage-banner"?: {
|
|
6
|
+
"homepage-banner-image"?: string;
|
|
7
|
+
"homepage-banner-title"?: string;
|
|
8
|
+
"homepage-banner-subtitle"?: string;
|
|
9
|
+
"homepage-banner-description"?: string;
|
|
10
|
+
"homepage-banner-button-name"?: string;
|
|
11
|
+
"homepage-banner-button-link"?: string;
|
|
12
|
+
};
|
|
13
|
+
}>;
|
|
14
|
+
"app-banner-array"?: Array<{
|
|
15
|
+
"app-banner"?: {
|
|
16
|
+
"app-banner-image"?: string;
|
|
17
|
+
"app-banner-title"?: string;
|
|
18
|
+
"app-banner-subtitle"?: string;
|
|
19
|
+
"app-banner-description"?: string;
|
|
20
|
+
"app-banner-button-name"?: string;
|
|
21
|
+
"app-banner-button-link"?: string;
|
|
22
|
+
"app-banner-link"?: string;
|
|
23
|
+
};
|
|
24
|
+
}>;
|
|
25
|
+
"website-description"?: string;
|
|
26
|
+
"website_description"?: string;
|
|
27
|
+
"why-choose-us-title"?: string;
|
|
28
|
+
"why-choose-us-features"?: Array<{
|
|
29
|
+
feature?: {
|
|
30
|
+
"feature-name"?: string;
|
|
31
|
+
"feature-icon"?: string;
|
|
32
|
+
};
|
|
33
|
+
"feature-name"?: string;
|
|
34
|
+
"feature-icon"?: string;
|
|
35
|
+
}>;
|
|
36
|
+
"contact-us"?: {
|
|
37
|
+
"contact-phone"?: string;
|
|
38
|
+
"contact-email"?: string;
|
|
39
|
+
"contact-address"?: string;
|
|
40
|
+
};
|
|
41
|
+
"social-links"?: Array<{
|
|
42
|
+
"social-link"?: {
|
|
43
|
+
"social-platform-name"?: string;
|
|
44
|
+
"social-platform-icon"?: string;
|
|
45
|
+
"social-platform-url"?: string;
|
|
46
|
+
};
|
|
47
|
+
"social-platform-name"?: string;
|
|
48
|
+
"social-platform-icon"?: string;
|
|
49
|
+
"social-platform-url"?: string;
|
|
50
|
+
}>;
|
|
51
|
+
"promo-bar"?: {
|
|
52
|
+
"promo-text"?: string;
|
|
53
|
+
"promo-code"?: string;
|
|
54
|
+
"promo-value"?: string;
|
|
55
|
+
"promo-active"?: boolean;
|
|
56
|
+
};
|
|
57
|
+
[key: string]: any;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export declare const getDynamicConfig: () => Promise<DynamicConfig | null>;
|
|
61
|
+
export declare const getLogoFromConfig: () => Promise<string | null>;
|
|
62
|
+
export declare const getBannerImageFromConfig: () => Promise<string | null>;
|
|
63
|
+
export declare const getMobileBannerFromConfig: () => Promise<{
|
|
64
|
+
image: string | null;
|
|
65
|
+
link: string | null;
|
|
66
|
+
}>;
|
|
67
|
+
export declare const getHomeBannersFromConfig: () => Promise<Array<{
|
|
68
|
+
image?: string;
|
|
69
|
+
title?: string;
|
|
70
|
+
subtitle?: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
buttonName?: string;
|
|
73
|
+
buttonLink?: string;
|
|
74
|
+
}> | null>;
|
|
75
|
+
export declare const getAppBannersFromConfig: () => Promise<Array<{
|
|
76
|
+
image?: string;
|
|
77
|
+
title?: string;
|
|
78
|
+
subtitle?: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
buttonName?: string;
|
|
81
|
+
buttonLink?: string;
|
|
82
|
+
}> | null>;
|
|
83
|
+
export declare const getMobileBannerImageFromConfig: () => Promise<string | null>;
|
|
84
|
+
export declare const getWebsiteDescriptionFromConfig: () => Promise<string | null>;
|
|
85
|
+
export declare const getFeaturesFromConfig: () => Promise<{
|
|
86
|
+
title: string;
|
|
87
|
+
features: Array<{
|
|
88
|
+
name: string;
|
|
89
|
+
icon: string;
|
|
90
|
+
}>;
|
|
91
|
+
} | null>;
|
|
92
|
+
export declare const getContactInfoFromConfig: () => Promise<{
|
|
93
|
+
phone?: string;
|
|
94
|
+
email?: string;
|
|
95
|
+
address?: string;
|
|
96
|
+
} | null>;
|
|
97
|
+
export declare const getTestimonialsFromConfig: () => Promise<{
|
|
98
|
+
title: string;
|
|
99
|
+
testimonials: Array<{
|
|
100
|
+
id: string;
|
|
101
|
+
text: string;
|
|
102
|
+
name: string;
|
|
103
|
+
rating: number;
|
|
104
|
+
avatar?: string;
|
|
105
|
+
}>;
|
|
106
|
+
} | null>;
|
|
107
|
+
export declare const getSocialLinksFromConfig: () => Promise<Array<{
|
|
108
|
+
name: string;
|
|
109
|
+
url: string;
|
|
110
|
+
icon?: string;
|
|
111
|
+
}> | null>;
|
|
112
|
+
export declare const getFaqsFromConfig: () => Promise<Array<{
|
|
113
|
+
category: string;
|
|
114
|
+
items: Array<{
|
|
115
|
+
q: string;
|
|
116
|
+
a: string;
|
|
117
|
+
}>;
|
|
118
|
+
}> | null>;
|
|
119
|
+
export declare const getPromoBarConfig: () => Promise<{
|
|
120
|
+
text: string | null;
|
|
121
|
+
code: string | null;
|
|
122
|
+
value: string | null;
|
|
123
|
+
active: boolean;
|
|
124
|
+
}>;
|
|
125
|
+
//# sourceMappingURL=dynamic-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-config.d.ts","sourceRoot":"","sources":["../../src/server/dynamic-config.ts"],"names":[],"mappings":"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"}
|