import fs from 'fs'; import path from 'path'; import matter from 'gray-matter'; import { mapSlugToFileSlug } from './slugs'; export interface ProductFrontmatter { title: string; sku: string; description: string; categories: string[]; images: string[]; locale: string; } export interface ProductMdx { slug: string; frontmatter: ProductFrontmatter; content: string; } export async function getProductMetadata( slug: string, locale: string, ): Promise | null> { // Map translated slug to file slug const fileSlug = await mapSlugToFileSlug(slug, locale); const productsDir = path.join(process.cwd(), 'data', 'products', locale); if (!fs.existsSync(productsDir)) return null; // Recursive search for the file const findFile = (dir: string): string | null => { const files = fs.readdirSync(dir); for (const file of files) { const fullPath = path.join(dir, file); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { const found = findFile(fullPath); if (found) return found; } else if (file === `${fileSlug}.mdx` || file === `${fileSlug}-2.mdx`) { return fullPath; } } return null; }; let filePath = findFile(productsDir); if (!filePath && locale !== 'en') { // Fallback to English const enProductsDir = path.join(process.cwd(), 'data', 'products', 'en'); if (fs.existsSync(enProductsDir)) { filePath = findFile(enProductsDir); } } if (filePath && fs.existsSync(filePath)) { const fileContent = fs.readFileSync(filePath, 'utf8'); const { data } = matter(fileContent); // Filter out products without images to match getProductBySlug behavior if (!data.images || data.images.length === 0 || !data.images[0]) { return null; } return { slug: fileSlug, frontmatter: { ...data, isFallback: filePath.includes('/en/'), } as any, }; } return null; } export async function getProductBySlug(slug: string, locale: string): Promise { // Map translated slug to file slug const fileSlug = await mapSlugToFileSlug(slug, locale); const productsDir = path.join(process.cwd(), 'data', 'products', locale); if (!fs.existsSync(productsDir)) return null; // Recursive search for the file const findFile = (dir: string): string | null => { const files = fs.readdirSync(dir); for (const file of files) { const fullPath = path.join(dir, file); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { const found = findFile(fullPath); if (found) return found; } else if (file === `${fileSlug}.mdx` || file === `${fileSlug}-2.mdx`) { return fullPath; } } return null; }; let filePath = findFile(productsDir); let isFallback = false; if (!filePath && locale !== 'en') { // Fallback to English const enProductsDir = path.join(process.cwd(), 'data', 'products', 'en'); if (fs.existsSync(enProductsDir)) { filePath = findFile(enProductsDir); if (filePath) isFallback = true; } } if (filePath && fs.existsSync(filePath)) { const fileContent = fs.readFileSync(filePath, 'utf8'); const { data, content } = matter(fileContent); const product = { slug: fileSlug, frontmatter: { ...data, isFallback, } as any, content, }; // Filter out products without images if ( !product.frontmatter.images || product.frontmatter.images.length === 0 || !product.frontmatter.images[0] ) { return null; } return product; } return null; } export async function getAllProductSlugs(locale: string): Promise { const productsDir = path.join(process.cwd(), 'data', 'products', locale); if (!fs.existsSync(productsDir)) return []; const slugs: string[] = []; const walk = (dir: string) => { const files = fs.readdirSync(dir); for (const file of files) { const fullPath = path.join(dir, file); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { walk(fullPath); } else if (file.endsWith('.mdx')) { slugs.push(file.replace(/\.mdx$/, '')); } } }; walk(productsDir); return slugs; } export async function getAllProducts(locale: string): Promise { const slugs = await getAllProductSlugs(locale); let allSlugs = slugs; if (locale !== 'en') { const enSlugs = await getAllProductSlugs('en'); allSlugs = Array.from(new Set([...slugs, ...enSlugs])); } const products = await Promise.all(allSlugs.map((slug) => getProductBySlug(slug, locale))); return products.filter((p): p is ProductMdx => p !== null); } export async function getAllProductsMetadata(locale: string): Promise[]> { const slugs = await getAllProductSlugs(locale); let allSlugs = slugs; if (locale !== 'en') { const enSlugs = await getAllProductSlugs('en'); allSlugs = Array.from(new Set([...slugs, ...enSlugs])); } const metadata = await Promise.all(allSlugs.map((slug) => getProductMetadata(slug, locale))); return metadata.filter((m): m is Partial => m !== null); }