Skip to content

Commit 415a1c7

Browse files
committed
feat: add feature toggle to all product fetches
1 parent faacafb commit 415a1c7

File tree

10 files changed

+256
-110
lines changed

10 files changed

+256
-110
lines changed
Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getCollectionByHandle } from "@lib/data"
12
import CollectionTemplate from "@modules/collections/templates"
23
import { Metadata } from "next"
34
import { notFound } from "next/navigation"
@@ -6,20 +7,10 @@ type Props = {
67
params: { handle: string }
78
}
89

9-
const BASEURL = process.env.NEXT_PUBLIC_BASE_URL ?? "http://localhost:8000"
10-
11-
async function getCollection(handle: string) {
12-
const res = await fetch(`${BASEURL}/api/collections/${handle}`)
13-
14-
if (!res.ok) {
15-
notFound()
16-
}
17-
18-
return res.json()
19-
}
20-
2110
export async function generateMetadata({ params }: Props): Promise<Metadata> {
22-
const { collection } = await getCollection(params.handle)
11+
const { collections } = await getCollectionByHandle(params.handle)
12+
13+
const collection = collections[0]
2314

2415
if (!collection) {
2516
notFound()
@@ -32,7 +23,9 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
3223
}
3324

3425
export default async function CollectionPage({ params }: Props) {
35-
const { collection } = await getCollection(params.handle)
26+
const { collections } = await getCollectionByHandle(params.handle)
27+
28+
const collection = collections[0]
3629

3730
return <CollectionTemplate collection={collection} />
3831
}

src/app/(main)/products/[handle]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getProductByHandle } from "@lib/medusa-fetch/products"
1+
import { getProductByHandle } from "@lib/data"
22
import ProductTemplate from "@modules/products/templates"
33
import { Metadata } from "next"
44
import { notFound } from "next/navigation"

src/app/api/collections/[handle]/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export async function GET(
5858
const nextPage = parseInt(page) + parseInt(limit)
5959

6060
return NextResponse.json({
61-
collection: collectionMeta,
61+
collections: [collectionMeta],
6262
response: {
6363
products: productsWithPrices,
6464
count,

src/lib/data/index.ts

Lines changed: 213 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,231 @@
1+
import medusaRequest from "../medusa-fetch"
12
import { StoreGetProductsParams } from "@medusajs/medusa"
23

3-
const API_BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:8000"
4-
5-
type FetchProductListParams = {
4+
type GetProductListParams = {
65
pageParam?: number
76
queryParams: StoreGetProductsParams
87
}
98

10-
export const fetchProductsList = async ({
9+
/**
10+
* This file contains functions for fetching products and collections from the Medusa API or the Medusa Product Module,
11+
* depending on the feature flag. By default, the standard Medusa API is used. To use the Medusa Product Module, set the feature flag to true.
12+
*/
13+
14+
// The feature flag is set in the store.config.json file. Restart the server after changing the flag for the changes to take effect.
15+
const PRODUCT_MODULE_ENABLED =
16+
process.env.FEATURE_PRODUCTMODULE_ENABLED || false
17+
18+
// The API_BASE_URL is set in the .env file. It is the base URL of your Next.js app.
19+
const API_BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:8000"
20+
21+
// Set DEBUG to true to console.log where the data is coming from.
22+
const DEBUG = true
23+
24+
/**
25+
* Fetches a product by handle, using the Medusa API or the Medusa Product Module, depending on the feature flag.
26+
* @param handle (string) - The handle of the product to retrieve
27+
* @returns (array) - An array of products (should only be one)
28+
*/
29+
export async function getProductByHandle(handle: string) {
30+
if (PRODUCT_MODULE_ENABLED) {
31+
DEBUG && console.log("PRODUCT_MODULE_ENABLED")
32+
const data = await fetch(`${API_BASE_URL}/api/products/${handle}`)
33+
.then((res) => res.json())
34+
.catch((err) => {
35+
throw err
36+
})
37+
38+
return data
39+
}
40+
41+
DEBUG && console.log("PRODUCT_MODULE_DISABLED")
42+
const { products } = await medusaRequest("GET", "/products", {
43+
query: {
44+
handle,
45+
},
46+
})
47+
.then((res) => res.body)
48+
.catch((err) => {
49+
throw err
50+
})
51+
52+
return {
53+
products,
54+
}
55+
}
56+
57+
/**
58+
* Fetches a list of products, using the Medusa API or the Medusa Product Module, depending on the feature flag.
59+
* @param pageParam (number) - The offset of the products to retrieve
60+
* @param queryParams (object) - The query parameters to pass to the API
61+
* @returns 'response' (object) - An object containing the products and the next page offset
62+
* @returns 'nextPage' (number) - The offset of the next page of products
63+
*/
64+
export async function getProductsList({
1165
pageParam = 0,
1266
queryParams,
13-
}: FetchProductListParams) => {
14-
const params = new URLSearchParams(queryParams as Record<string, string>)
67+
}: GetProductListParams) {
68+
const limit = queryParams.limit || 12
69+
70+
if (PRODUCT_MODULE_ENABLED) {
71+
console.log("PRODUCT_MODULE_ENABLED")
72+
const params = new URLSearchParams(queryParams as Record<string, string>)
73+
74+
const { products, count, nextPage } = await fetch(
75+
`${API_BASE_URL}/api/products?limit=${limit}&offset=${pageParam}&${params.toString()}`,
76+
{
77+
next: {
78+
tags: ["products"],
79+
},
80+
}
81+
).then((res) => res.json())
82+
83+
return {
84+
response: { products, count },
85+
nextPage,
86+
}
87+
}
1588

16-
const { products, count, nextPage } = await fetch(
17-
`${API_BASE_URL}/api/products?limit=12&offset=${pageParam}&${params.toString()}`,
89+
DEBUG && console.log("PRODUCT_MODULE_DISABLED")
90+
const { products, count, nextPage } = await medusaRequest(
91+
"GET",
92+
"/products",
1893
{
19-
next: {
20-
tags: ["products"],
94+
query: {
95+
limit,
96+
offset: pageParam,
97+
...queryParams,
2198
},
2299
}
23-
).then((res) => res.json())
100+
)
101+
.then((res) => res.body)
102+
.catch((err) => {
103+
throw err
104+
})
24105

25106
return {
26107
response: { products, count },
27108
nextPage,
28109
}
29110
}
111+
112+
/**
113+
* Fetches a list of collections, using the Medusa API or the Medusa Product Module, depending on the feature flag.
114+
* @param offset (number) - The offset of the collections to retrieve (default: 0
115+
* @returns collections (array) - An array of collections
116+
* @returns count (number) - The total number of collections
117+
*/
118+
export async function getCollectionsList(offset: number = 0) {
119+
if (PRODUCT_MODULE_ENABLED) {
120+
DEBUG && console.log("PRODUCT_MODULE_ENABLED")
121+
const { collections, count } = await fetch(
122+
`${API_BASE_URL}/api/collections?offset=${offset}`,
123+
{
124+
next: {
125+
tags: ["collections"],
126+
},
127+
}
128+
)
129+
.then((res) => res.json())
130+
.catch((err) => {
131+
throw err
132+
})
133+
134+
return {
135+
collections,
136+
count,
137+
}
138+
}
139+
140+
DEBUG && console.log("PRODUCT_MODULE_DISABLED")
141+
const { collections, count } = await medusaRequest("GET", "/collections", {
142+
query: {
143+
offset,
144+
},
145+
})
146+
.then((res) => res.body)
147+
.catch((err) => {
148+
throw err
149+
})
150+
151+
return {
152+
collections,
153+
count,
154+
}
155+
}
156+
157+
/**
158+
* Fetches a collection by handle, using the Medusa API or the Medusa Product Module, depending on the feature flag.
159+
* @param handle (string) - The handle of the collection to retrieve
160+
* @returns (array) - An array of collections (should only be one)
161+
*/
162+
export async function getCollectionByHandle(handle: string) {
163+
if (PRODUCT_MODULE_ENABLED) {
164+
DEBUG && console.log("PRODUCT_MODULE_ENABLED")
165+
const data = await fetch(`${API_BASE_URL}/api/collections/${handle}`)
166+
.then((res) => res.json())
167+
.catch((err) => {
168+
throw err
169+
})
170+
171+
return data
172+
}
173+
174+
DEBUG && console.log("PRODUCT_MODULE_DISABLED")
175+
const data = await medusaRequest("GET", "/collections", {
176+
query: {
177+
handle: [handle],
178+
},
179+
})
180+
.then((res) => res.body)
181+
.catch((err) => {
182+
throw err
183+
})
184+
185+
return data
186+
}
187+
188+
export async function getProductsByCollectionHandle({
189+
pageParam = 0,
190+
handle,
191+
cartId,
192+
}: {
193+
pageParam?: number
194+
handle: string
195+
cartId?: string
196+
}) {
197+
if (PRODUCT_MODULE_ENABLED) {
198+
DEBUG && console.log("PRODUCT_MODULE_ENABLED")
199+
const { response, nextPage } = await fetch(
200+
`${API_BASE_URL}/api/collections/${handle}?cart_id=${cartId}&page=${pageParam.toString()}`
201+
)
202+
.then((res) => res.json())
203+
.catch((err) => {
204+
throw err
205+
})
206+
207+
return {
208+
response,
209+
nextPage,
210+
}
211+
}
212+
213+
DEBUG && console.log("PRODUCT_MODULE_DISABLED")
214+
const { id } = await getCollectionByHandle(handle).then(
215+
(res) => res.collections[0]
216+
)
217+
218+
const { response, nextPage } = await getProductsList({
219+
pageParam,
220+
queryParams: { collection_id: [id], cart_id: cartId },
221+
})
222+
.then((res) => res)
223+
.catch((err) => {
224+
throw err
225+
})
226+
227+
return {
228+
response,
229+
nextPage,
230+
}
231+
}

src/lib/hooks/use-layout-data.tsx

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getProductsList, getCollectionsList } from "@lib/data"
12
import { getPercentageDiff } from "@lib/util/get-precentage-diff"
23
import { ProductCollection, Region } from "@medusajs/medusa"
34
import { PricedProduct } from "@medusajs/medusa/dist/types/pricing"
@@ -17,15 +18,8 @@ const fetchCollectionData = async (): Promise<LayoutCollection[]> => {
1718
let count = 1
1819

1920
do {
20-
await fetch(
21-
`${process.env.NEXT_PUBLIC_BASE_URL}/api/collections?offset=${offset}`,
22-
{
23-
next: {
24-
tags: ["collections"],
25-
},
26-
}
27-
)
28-
.then((res) => res.json())
21+
await getCollectionsList(offset)
22+
.then((res) => res)
2923
.then(({ collections: newCollections, count: newCount }) => {
3024
collections = [...collections, ...newCollections]
3125
count = newCount
@@ -57,15 +51,15 @@ const fetchFeaturedProducts = async (
5751
cartId: string,
5852
region: Region
5953
): Promise<ProductPreviewType[]> => {
60-
const products: PricedProduct[] = await fetch(
61-
`${process.env.NEXT_PUBLIC_BASE_URL}/api/products?limit=4&cart_id=${cartId}&region_id=${region.id}`,
62-
{
63-
next: {
64-
tags: ["products"],
65-
},
66-
}
67-
)
68-
.then((res) => res.json())
54+
const products: PricedProduct[] = await getProductsList({
55+
pageParam: 4,
56+
queryParams: {
57+
limit: 4,
58+
cart_id: cartId,
59+
region_id: region.id,
60+
},
61+
})
62+
.then((res) => res.response)
6963
.then(({ products }) => products)
7064
.catch((_) => [] as PricedProduct[])
7165

src/lib/medusa-fetch/index.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,18 @@ export default async function medusaRequest(
2323
},
2424
}
2525

26-
if (payload) {
27-
if ("body" in payload) {
28-
options.body = JSON.stringify(payload.body)
29-
}
30-
if ("query" in payload) {
31-
const params = objectToURLSearchParams(payload.query!).toString()
32-
path = `${path}?${params}`
33-
}
26+
if (payload?.body) {
27+
options.body = JSON.stringify(payload.body)
28+
}
29+
30+
if (payload?.query) {
31+
const params = objectToURLSearchParams(payload.query!).toString()
32+
path = `${path}?${params}`
3433
}
3534

35+
const limit = payload?.query?.limit || 100
36+
const offset = payload?.query?.offset || 0
37+
3638
try {
3739
const result = await fetch(`${ENDPOINT}/store${path}`, options)
3840
const body = await result.json()
@@ -41,6 +43,10 @@ export default async function medusaRequest(
4143
throw body.errors[0]
4244
}
4345

46+
const nextPage = offset + limit
47+
48+
body.nextPage = body.count > nextPage ? nextPage : null
49+
4450
return {
4551
status: result.status,
4652
ok: result.ok,

0 commit comments

Comments
 (0)