diff --git a/app/[page]/page.tsx b/app/[page]/page.tsx index 1165adb0a..638958ace 100644 --- a/app/[page]/page.tsx +++ b/app/[page]/page.tsx @@ -6,7 +6,7 @@ import { notFound } from 'next/navigation'; export const runtime = 'edge'; -export const revalidate = parseInt(process.env.REVALIDATE_WINDOW ?? `${60 * 60 * 12}`); // 12 hours +export const revalidate = 43200; // 12 hours export async function generateMetadata({ params diff --git a/app/api/revalidate/route.ts b/app/api/revalidate/route.ts index 47af2a4a4..c1ed21a12 100644 --- a/app/api/revalidate/route.ts +++ b/app/api/revalidate/route.ts @@ -1,4 +1,4 @@ -import { revalidate } from 'lib/shopify'; +import { revalidate } from 'lib/medusa'; import { NextRequest, NextResponse } from 'next/server'; export const runtime = 'edge'; diff --git a/app/page.tsx b/app/page.tsx index 465600f39..be8e83f60 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -5,7 +5,7 @@ import { Suspense } from 'react'; export const runtime = 'edge'; -export const revalidate = parseInt(process.env.REVALIDATE_WINDOW ?? `${60 * 60 * 12}`); // 12 hours +export const revalidate = 43200; // 12 hours export const metadata = { description: 'High-performance ecommerce store built with Next.js, Vercel, and Medusa.', diff --git a/app/search/[collection]/page.tsx b/app/search/[collection]/page.tsx index afad43c40..e0516d3e8 100644 --- a/app/search/[collection]/page.tsx +++ b/app/search/[collection]/page.tsx @@ -33,11 +33,7 @@ export default async function CategoryPage({ }) { const { sort } = searchParams as { [key: string]: string }; const { sortKey, reverse } = sorting.find((item) => item.slug === sort) || defaultSort; - const products = await getCategoryProducts( - params.collection - // sortKey, - // reverse - ); + const products = await getCategoryProducts(params.collection, reverse, sortKey); return (
diff --git a/lib/medusa/index.ts b/lib/medusa/index.ts index 9b3104906..2ea99b5f2 100644 --- a/lib/medusa/index.ts +++ b/lib/medusa/index.ts @@ -1,6 +1,10 @@ import { isMedusaError } from 'lib/type-guards'; +import { TAGS } from 'lib/constants'; import { mapOptionIds } from 'lib/utils'; +import { revalidateTag } from 'next/cache'; +import { headers } from 'next/headers'; +import { NextRequest, NextResponse } from 'next/server'; import { calculateVariantAmount, computeAmount, convertToDecimal } from './helpers'; import { Cart, @@ -346,7 +350,11 @@ export async function getCategory(handle: string): Promise { +export async function getCategoryProducts( + handle: string, + reverse: boolean, + sortKey: string +): Promise { const res = await medusaRequest('GET', `/product-categories?handle=${handle}`); if (!res) { @@ -355,13 +363,9 @@ export async function getCategoryProducts(handle: string): Promise { const category = res.body.product_categories[0]; - const category_products = await medusaRequest('GET', `/products?category_id[]=${category.id}`); + const category_products = await getProducts({ reverse, sortKey, categoryId: category.id }); - const products: Product[] = category_products.body.products.map((product: MedusaProduct) => - reshapeProduct(product) - ); - - return products; + return category_products; } export async function getProduct(handle: string): Promise { @@ -371,16 +375,32 @@ export async function getProduct(handle: string): Promise { } export async function getProducts({ - query = '', + query, reverse, - sortKey + sortKey, + categoryId }: { query?: string; reverse?: boolean; sortKey?: string; + categoryId?: string; }): Promise { - const res = await medusaRequest('GET', `/products?q=${query}&limit=20`); - let products: Product[] = res.body.products.map((product: MedusaProduct) => + let res; + + if (query) { + res = await medusaRequest('GET', `/products?q=${query}&limit=100`); + } else if (categoryId) { + res = await medusaRequest('GET', `/products?category_id[]=${categoryId}&limit=100`); + } else { + res = await medusaRequest('GET', `/products?limit=100`); + } + + if (!res) { + console.log("Couldn't fetch products"); + return []; + } + + let products: Product[] = res?.body.products.map((product: MedusaProduct) => reshapeProduct(product) ); @@ -418,3 +438,27 @@ export async function getMenu(menu: string): Promise { return []; } + +// This is called from `app/api/revalidate.ts` so providers can control revalidation logic. +export async function revalidate(req: NextRequest): Promise { + const collectionWebhooks = ['collections/create', 'collections/delete', 'collections/update']; + const productWebhooks = ['products/create', 'products/delete', 'products/update']; + const topic = headers().get('x-medusa-topic') || 'unknown'; + const isCollectionUpdate = collectionWebhooks.includes(topic); + const isProductUpdate = productWebhooks.includes(topic); + + if (!isCollectionUpdate && !isProductUpdate) { + // We don't need to revalidate anything for any other topics. + return NextResponse.json({ status: 200 }); + } + + if (isCollectionUpdate) { + revalidateTag(TAGS.collections); + } + + if (isProductUpdate) { + revalidateTag(TAGS.products); + } + + return NextResponse.json({ status: 200, revalidated: true, now: Date.now() }); +}