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,378 @@
|
|
|
1
|
+
"use server"
|
|
2
|
+
|
|
3
|
+
import { sdk } from "../config"
|
|
4
|
+
import { sortProducts, type SortOptions } from "../util/sort-products"
|
|
5
|
+
import { HttpTypes } from "@medusajs/types"
|
|
6
|
+
import { getAuthHeaders, getCacheOptions } from "../cookies"
|
|
7
|
+
import { getRegion, retrieveRegion } from "./regions"
|
|
8
|
+
import Color from "color"
|
|
9
|
+
|
|
10
|
+
export const listProducts = async ({
|
|
11
|
+
pageParam = 1,
|
|
12
|
+
queryParams,
|
|
13
|
+
countryCode,
|
|
14
|
+
regionId,
|
|
15
|
+
}: {
|
|
16
|
+
pageParam?: number
|
|
17
|
+
queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductListParams
|
|
18
|
+
countryCode?: string
|
|
19
|
+
regionId?: string
|
|
20
|
+
}): Promise<{
|
|
21
|
+
response: { products: HttpTypes.StoreProduct[]; count: number }
|
|
22
|
+
nextPage: number | null
|
|
23
|
+
queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductListParams
|
|
24
|
+
}> => {
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if (!countryCode && !regionId) {
|
|
28
|
+
|
|
29
|
+
throw new Error("Country code or region ID is required")
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const limit = queryParams?.limit || 12
|
|
33
|
+
const _pageParam = Math.max(pageParam, 1)
|
|
34
|
+
const offset = _pageParam === 1 ? 0 : (_pageParam - 1) * limit
|
|
35
|
+
|
|
36
|
+
let region: HttpTypes.StoreRegion | undefined | null
|
|
37
|
+
|
|
38
|
+
if (countryCode) {
|
|
39
|
+
|
|
40
|
+
region = await getRegion(countryCode)
|
|
41
|
+
} else {
|
|
42
|
+
|
|
43
|
+
region = await retrieveRegion(regionId!)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!region) {
|
|
47
|
+
return {
|
|
48
|
+
response: { products: [], count: 0 },
|
|
49
|
+
nextPage: null,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
const headers = {
|
|
56
|
+
...(await getAuthHeaders()),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const next = {
|
|
60
|
+
...(await getCacheOptions("products")),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 1. Standard Medusa query parameters
|
|
64
|
+
const standardQuery: any = {
|
|
65
|
+
limit,
|
|
66
|
+
offset,
|
|
67
|
+
region_id: region?.id,
|
|
68
|
+
fields:
|
|
69
|
+
"*variants.calculated_price,+variants.inventory_quantity,*variants.images,+variants.metadata,+variants.options,+metadata,+tags,+average_rating,+total_rating_count,+total_rating_sum,",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 2. Identify advanced filters that require the product-helper API
|
|
73
|
+
const advancedFilterKeys = [
|
|
74
|
+
"metadata", "min_price", "max_price", "q", "collection_id", "category_id",
|
|
75
|
+
"tags", "option_value", "gender", "color", "material", "style", "brand",
|
|
76
|
+
"type", "product_type", "order"
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
const hasAdvancedFilters = !!(queryParams && Object.keys(queryParams).some(key =>
|
|
80
|
+
advancedFilterKeys.includes(key) && (queryParams as any)[key] !== undefined
|
|
81
|
+
))
|
|
82
|
+
|
|
83
|
+
const endpoint = hasAdvancedFilters ? "/store/product-helper/products" : "/store/products";
|
|
84
|
+
|
|
85
|
+
let finalQuery: any = { ...standardQuery }
|
|
86
|
+
|
|
87
|
+
if (hasAdvancedFilters) {
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
// We use URLSearchParams to ensure correct formatting and handle repeated keys if needed
|
|
91
|
+
const params = new URLSearchParams()
|
|
92
|
+
|
|
93
|
+
// 1. Add standard params
|
|
94
|
+
params.append("limit", limit.toString())
|
|
95
|
+
params.append("offset", offset.toString())
|
|
96
|
+
if (region?.id) params.append("region_id", region.id)
|
|
97
|
+
|
|
98
|
+
// Use '*' for helper endpoint to let it resolve necessary relations
|
|
99
|
+
params.append("fields", "*")
|
|
100
|
+
|
|
101
|
+
// 2. Map queryParams
|
|
102
|
+
for (const [key, value] of Object.entries(queryParams || {})) {
|
|
103
|
+
if (["metadata", "min_price", "max_price", "limit", "offset", "region_id", "fields"].includes(key)) continue
|
|
104
|
+
|
|
105
|
+
const values = Array.isArray(value) ? value : [value]
|
|
106
|
+
const lowerKey = key.toLowerCase()
|
|
107
|
+
|
|
108
|
+
if (lowerKey === "color") {
|
|
109
|
+
// Map 'color' filter to 'option_value' which backend understands for variants
|
|
110
|
+
values.forEach(v => params.append("option_value[]", String(v)))
|
|
111
|
+
} else if (["material", "gender", "product_type", "type", "style", "brand"].includes(lowerKey)) {
|
|
112
|
+
// Map these to metadata as they are defined as metadata in your config
|
|
113
|
+
const metaKey = lowerKey === "type" ? "product_type" : lowerKey
|
|
114
|
+
values.forEach(v => params.append(`metadata[${metaKey}]`, String(v)))
|
|
115
|
+
} else {
|
|
116
|
+
// Standard mapping for others (tags, collection_id, etc.)
|
|
117
|
+
if (Array.isArray(value)) {
|
|
118
|
+
value.forEach(v => params.append(`${key}[]`, String(v)))
|
|
119
|
+
} else if (value !== undefined && value !== null) {
|
|
120
|
+
params.append(key, String(value))
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 3. Map price filters (min_price -> price_min, max_price -> price_max)
|
|
126
|
+
if ((queryParams as any).min_price) params.append("price_min", String((queryParams as any).min_price))
|
|
127
|
+
if ((queryParams as any).max_price) params.append("price_max", String((queryParams as any).max_price))
|
|
128
|
+
|
|
129
|
+
// 4. Map metadata filters to metadata[key] format
|
|
130
|
+
if ((queryParams as any).metadata) {
|
|
131
|
+
for (const [key, value] of Object.entries((queryParams as any).metadata)) {
|
|
132
|
+
const values = Array.isArray(value) ? value : [value]
|
|
133
|
+
|
|
134
|
+
values.forEach(v => {
|
|
135
|
+
if (key.toLowerCase() === "color") {
|
|
136
|
+
// Map color in metadata to option_value[]
|
|
137
|
+
params.append("option_value[]", String(v))
|
|
138
|
+
} else {
|
|
139
|
+
// Standard metadata format: metadata[key]=value
|
|
140
|
+
params.append(`metadata[${key}]`, String(v))
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
finalQuery = params
|
|
147
|
+
|
|
148
|
+
} else {
|
|
149
|
+
// Standard endpoint - only merge known safe Medusa keys from queryParams
|
|
150
|
+
// to avoid "Unrecognized fields" errors
|
|
151
|
+
const safeKeys = ["order", "id", "handle", "status", "created_at", "updated_at", "type_id"]
|
|
152
|
+
for (const key of safeKeys) {
|
|
153
|
+
if (queryParams && (queryParams as any)[key]) {
|
|
154
|
+
finalQuery[key] = (queryParams as any)[key]
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Use the appended query string to avoid SDK's default serialization issues with brackets
|
|
160
|
+
const requestUrl = hasAdvancedFilters ? `${endpoint}?${finalQuery.toString()}` : endpoint;
|
|
161
|
+
|
|
162
|
+
return sdk.client
|
|
163
|
+
.fetch<{ products: HttpTypes.StoreProduct[]; count: number }>(
|
|
164
|
+
requestUrl,
|
|
165
|
+
{
|
|
166
|
+
method: "GET",
|
|
167
|
+
query: hasAdvancedFilters ? undefined : finalQuery,
|
|
168
|
+
headers,
|
|
169
|
+
next: {
|
|
170
|
+
...next,
|
|
171
|
+
revalidate: 0, // Disable Next.js cache for now to show logs
|
|
172
|
+
},
|
|
173
|
+
cache: "no-store", // Ensure it hits backend every time for testing
|
|
174
|
+
}
|
|
175
|
+
)
|
|
176
|
+
.then(({ products, count }) => {
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
const nextPage = count > offset + limit ? _pageParam + 1 : null
|
|
180
|
+
|
|
181
|
+
if (products && products.length > 0) {
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
response: {
|
|
187
|
+
products: products || [],
|
|
188
|
+
count: count || 0,
|
|
189
|
+
},
|
|
190
|
+
nextPage: nextPage,
|
|
191
|
+
queryParams,
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
.catch((error) => {
|
|
195
|
+
throw error
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* This will fetch 100 products to the Next.js cache and sort them based on the sortBy parameter.
|
|
201
|
+
* It will then return the paginated products based on the page and limit parameters.
|
|
202
|
+
*/
|
|
203
|
+
export const listProductsWithSort = async ({
|
|
204
|
+
page = 1,
|
|
205
|
+
queryParams,
|
|
206
|
+
sortBy = "created_at_desc",
|
|
207
|
+
countryCode,
|
|
208
|
+
}: {
|
|
209
|
+
page?: number
|
|
210
|
+
queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams
|
|
211
|
+
sortBy?: SortOptions
|
|
212
|
+
countryCode: string
|
|
213
|
+
}): Promise<{
|
|
214
|
+
response: { products: HttpTypes.StoreProduct[]; count: number }
|
|
215
|
+
nextPage: number | null
|
|
216
|
+
queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams
|
|
217
|
+
}> => {
|
|
218
|
+
const limit = queryParams?.limit || 12
|
|
219
|
+
|
|
220
|
+
// Directly fetch from backend with correct pagination
|
|
221
|
+
// This ensures the backend terminal logs the specific request
|
|
222
|
+
const {
|
|
223
|
+
response: { products, count },
|
|
224
|
+
} = await listProducts({
|
|
225
|
+
pageParam: page,
|
|
226
|
+
queryParams: {
|
|
227
|
+
...queryParams,
|
|
228
|
+
limit,
|
|
229
|
+
},
|
|
230
|
+
countryCode,
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
// Sorting is now handled natively by the backend API via the 'order' query param.
|
|
234
|
+
const finalProducts = products
|
|
235
|
+
|
|
236
|
+
const nextPage = count > page * limit ? page + 1 : null
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
response: {
|
|
240
|
+
products: finalProducts,
|
|
241
|
+
count,
|
|
242
|
+
},
|
|
243
|
+
nextPage,
|
|
244
|
+
queryParams,
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Fetch products that have a specific tag value
|
|
250
|
+
*/
|
|
251
|
+
export async function getProductsByTag({
|
|
252
|
+
tagValue,
|
|
253
|
+
limit = 12,
|
|
254
|
+
countryCode,
|
|
255
|
+
}: {
|
|
256
|
+
tagValue: string
|
|
257
|
+
limit?: number
|
|
258
|
+
countryCode: string
|
|
259
|
+
}) {
|
|
260
|
+
try {
|
|
261
|
+
const result = await listProducts({
|
|
262
|
+
queryParams: { tags: [tagValue], limit },
|
|
263
|
+
countryCode,
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
return result.response.products
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.error("Error fetching products by tag:", error)
|
|
269
|
+
return []
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Fetch dynamic filter options from the backend API
|
|
275
|
+
*/
|
|
276
|
+
export const getDynamicFilters = async (countryCode: string) => {
|
|
277
|
+
const backendUrl = process.env.MEDUSA_BACKEND_URL || "http://localhost:9000"
|
|
278
|
+
const publishableKey = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
if (!publishableKey) return { genders: [], productTypes: [], materials: [], colors: [] }
|
|
282
|
+
|
|
283
|
+
const response = await fetch(`${backendUrl}/store/product-helper/filters`, {
|
|
284
|
+
method: "GET",
|
|
285
|
+
headers: {
|
|
286
|
+
"Content-Type": "application/json",
|
|
287
|
+
"x-publishable-api-key": publishableKey,
|
|
288
|
+
},
|
|
289
|
+
cache: "no-store",
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
if (!response.ok) {
|
|
293
|
+
return { genders: [], productTypes: [], materials: [], colors: [] }
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const data = await response.json()
|
|
297
|
+
|
|
298
|
+
const formatLabel = (str: string) => {
|
|
299
|
+
return str
|
|
300
|
+
.split(/[_-]/)
|
|
301
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
302
|
+
.join(' ')
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const metadata = data.metadata || {}
|
|
306
|
+
const variantOptions = data.variant_options || []
|
|
307
|
+
|
|
308
|
+
// Gather all unique colors from all possible sources
|
|
309
|
+
const colorSet = new Set<string>()
|
|
310
|
+
|
|
311
|
+
// 1. From variant options (check all options with title 'color')
|
|
312
|
+
variantOptions.forEach((o: any) => {
|
|
313
|
+
if (o.option_title.toLowerCase() === 'color' || o.option_title.toLowerCase() === 'colour') {
|
|
314
|
+
o.values?.forEach((v: string) => {
|
|
315
|
+
if (v) colorSet.add(v.trim().toLowerCase())
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
// 2. From metadata colors (handle newline/comma separated values)
|
|
321
|
+
if (metadata.color) {
|
|
322
|
+
metadata.color.forEach((c: string) => {
|
|
323
|
+
if (c) {
|
|
324
|
+
const parts = c.split(/[,/\n\r]+/).map(s => s.trim()).filter(Boolean)
|
|
325
|
+
parts.forEach(p => colorSet.add(p.toLowerCase()))
|
|
326
|
+
}
|
|
327
|
+
})
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
genders: (metadata.gender || []).sort().map((g: string) => ({
|
|
332
|
+
value: g,
|
|
333
|
+
label: formatLabel(g)
|
|
334
|
+
})),
|
|
335
|
+
productTypes: (data.product_types || []).sort((a: any, b: any) => a.label.localeCompare(b.label)).map((t: any) => ({
|
|
336
|
+
value: t.label,
|
|
337
|
+
label: formatLabel(t.label)
|
|
338
|
+
})),
|
|
339
|
+
materials: (metadata.material || []).sort().map((m: string) => ({
|
|
340
|
+
value: m,
|
|
341
|
+
label: formatLabel(m)
|
|
342
|
+
})),
|
|
343
|
+
colors: Array.from(colorSet).sort().map((c: string) => {
|
|
344
|
+
let hex = ""
|
|
345
|
+
try {
|
|
346
|
+
// Try to resolve color hex code using the Color library
|
|
347
|
+
hex = Color(c.replace(/\s+/g, '').toLowerCase()).hex()
|
|
348
|
+
} catch (e) {
|
|
349
|
+
try {
|
|
350
|
+
hex = Color(c.toLowerCase()).hex()
|
|
351
|
+
} catch (e2) {
|
|
352
|
+
// No hex found
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
value: c,
|
|
357
|
+
label: formatLabel(c),
|
|
358
|
+
hex
|
|
359
|
+
}
|
|
360
|
+
})
|
|
361
|
+
}
|
|
362
|
+
} catch (error) {
|
|
363
|
+
console.error("Error fetching dynamic filters:", error)
|
|
364
|
+
return { genders: [], productTypes: [], materials: [], colors: [] }
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Fetch a single product by its handle
|
|
370
|
+
*/
|
|
371
|
+
export async function getProductByHandle(handle: string) {
|
|
372
|
+
const result = await sdk.store.product.list(
|
|
373
|
+
{ handle, fields: "*variants.calculated_price,+variants.inventory_quantity,+variants.manage_inventory,+variants.allow_backorder,*variants.options,*options,*options.values,*images,*thumbnail,+metadata" },
|
|
374
|
+
{ next: { tags: ["products"] } }
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
return result.products[0]
|
|
378
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use server"
|
|
2
|
+
|
|
3
|
+
import { sdk } from "../config"
|
|
4
|
+
import medusaError from "../util/medusa-error"
|
|
5
|
+
import { HttpTypes } from "@medusajs/types"
|
|
6
|
+
import { getCacheOptions } from "../cookies"
|
|
7
|
+
|
|
8
|
+
export const listRegions = async () => {
|
|
9
|
+
const next = {
|
|
10
|
+
...(await getCacheOptions("regions")),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return sdk.client
|
|
14
|
+
.fetch<{ regions: HttpTypes.StoreRegion[] }>(`/store/regions`, {
|
|
15
|
+
method: "GET",
|
|
16
|
+
next,
|
|
17
|
+
cache: "force-cache",
|
|
18
|
+
})
|
|
19
|
+
.then(({ regions }) => regions)
|
|
20
|
+
.catch(medusaError)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const retrieveRegion = async (id: string) => {
|
|
24
|
+
const next = {
|
|
25
|
+
...(await getCacheOptions(["regions", id].join("-"))),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return sdk.client
|
|
29
|
+
.fetch<{ region: HttpTypes.StoreRegion }>(`/store/regions/${id}`, {
|
|
30
|
+
method: "GET",
|
|
31
|
+
next,
|
|
32
|
+
cache: "force-cache",
|
|
33
|
+
})
|
|
34
|
+
.then(({ region }) => region)
|
|
35
|
+
.catch(medusaError)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const regionMap = new Map<string, HttpTypes.StoreRegion>()
|
|
39
|
+
|
|
40
|
+
export const getRegion = async (countryCode: string) => {
|
|
41
|
+
try {
|
|
42
|
+
if (regionMap.has(countryCode)) {
|
|
43
|
+
return regionMap.get(countryCode)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const regions = await listRegions()
|
|
47
|
+
|
|
48
|
+
if (!regions) {
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
regions.forEach((region) => {
|
|
53
|
+
region.countries?.forEach((c) => {
|
|
54
|
+
regionMap.set(c?.iso_2 ?? "", region)
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const region = countryCode
|
|
59
|
+
? regionMap.get(countryCode)
|
|
60
|
+
: regionMap.get("us")
|
|
61
|
+
|
|
62
|
+
return region
|
|
63
|
+
} catch (e: any) {
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
}
|