products.ts
1 "use server" 2 3 import { sdk } from "@lib/config" 4 import { sortProducts } from "@lib/util/sort-products" 5 import { HttpTypes } from "@medusajs/types" 6 import { SortOptions } from "@modules/store/components/refinement-list/sort-products" 7 import { getAuthHeaders, getCacheOptions } from "./cookies" 8 import { getRegion, retrieveRegion } from "./regions" 9 10 export const listProducts = async ({ 11 pageParam = 1, 12 queryParams, 13 countryCode, 14 regionId, 15 }: { 16 pageParam?: number 17 queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams 18 countryCode?: string 19 regionId?: string 20 }): Promise<{ 21 response: { products: HttpTypes.StoreProduct[]; count: number } 22 nextPage: number | null 23 queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams 24 }> => { 25 if (!countryCode && !regionId) { 26 throw new Error("Country code or region ID is required") 27 } 28 29 const limit = queryParams?.limit || 12 30 const _pageParam = Math.max(pageParam, 1) 31 const offset = (_pageParam === 1) ? 0 : (_pageParam - 1) * limit; 32 33 let region: HttpTypes.StoreRegion | undefined | null 34 35 if (countryCode) { 36 region = await getRegion(countryCode) 37 } else { 38 region = await retrieveRegion(regionId!) 39 } 40 41 if (!region) { 42 return { 43 response: { products: [], count: 0 }, 44 nextPage: null, 45 } 46 } 47 48 const headers = { 49 ...(await getAuthHeaders()), 50 } 51 52 const next = { 53 ...(await getCacheOptions("products")), 54 } 55 56 return sdk.client 57 .fetch<{ products: HttpTypes.StoreProduct[]; count: number }>( 58 `/store/products`, 59 { 60 method: "GET", 61 query: { 62 limit, 63 offset, 64 region_id: region?.id, 65 fields: 66 "*variants.calculated_price,+variants.inventory_quantity,+metadata,+tags", 67 ...queryParams, 68 }, 69 headers, 70 next, 71 cache: "force-cache", 72 } 73 ) 74 .then(({ products, count }) => { 75 const nextPage = count > offset + limit ? pageParam + 1 : null 76 77 return { 78 response: { 79 products, 80 count, 81 }, 82 nextPage: nextPage, 83 queryParams, 84 } 85 }) 86 } 87 88 /** 89 * This will fetch 100 products to the Next.js cache and sort them based on the sortBy parameter. 90 * It will then return the paginated products based on the page and limit parameters. 91 */ 92 export const listProductsWithSort = async ({ 93 page = 0, 94 queryParams, 95 sortBy = "created_at", 96 countryCode, 97 }: { 98 page?: number 99 queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams 100 sortBy?: SortOptions 101 countryCode: string 102 }): Promise<{ 103 response: { products: HttpTypes.StoreProduct[]; count: number } 104 nextPage: number | null 105 queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams 106 }> => { 107 const limit = queryParams?.limit || 12 108 109 const { 110 response: { products, count }, 111 } = await listProducts({ 112 pageParam: 0, 113 queryParams: { 114 ...queryParams, 115 limit: 100, 116 }, 117 countryCode, 118 }) 119 120 const sortedProducts = sortProducts(products, sortBy) 121 122 const pageParam = (page - 1) * limit 123 124 const nextPage = count > pageParam + limit ? pageParam + limit : null 125 126 const paginatedProducts = sortedProducts.slice(pageParam, pageParam + limit) 127 128 return { 129 response: { 130 products: paginatedProducts, 131 count, 132 }, 133 nextPage, 134 queryParams, 135 } 136 }