Files
klz-cables.com/lib/mdx.ts
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

176 lines
5.2 KiB
TypeScript

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<Partial<ProductMdx> | null> {
// Map translated slug to file slug
const fileSlug = await mapSlugToFileSlug(slug, locale);
const productsDir = path.join(process.cwd(), 'data', 'products', locale);
// Try exact slug first
let filePath = path.join(productsDir, `${fileSlug}.mdx`);
if (!fs.existsSync(filePath)) {
// Try with -2 suffix (common in the dumped files)
filePath = path.join(productsDir, `${fileSlug}-2.mdx`);
}
if (!fs.existsSync(filePath)) {
// Fallback to English if locale is not 'en'
if (locale !== 'en') {
const enProductsDir = path.join(process.cwd(), 'data', 'products', 'en');
let enFilePath = path.join(enProductsDir, `${fileSlug}.mdx`);
if (!fs.existsSync(enFilePath)) {
enFilePath = path.join(enProductsDir, `${fileSlug}-2.mdx`);
}
if (fs.existsSync(enFilePath)) {
const fileContent = fs.readFileSync(enFilePath, '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: true,
} as ProductFrontmatter & { isFallback?: boolean },
};
}
}
} else {
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 as ProductFrontmatter,
};
}
return null;
}
export async function getProductBySlug(slug: string, locale: string): Promise<ProductMdx | null> {
// Map translated slug to file slug
const fileSlug = await mapSlugToFileSlug(slug, locale);
const productsDir = path.join(process.cwd(), 'data', 'products', locale);
// Try exact slug first
let filePath = path.join(productsDir, `${fileSlug}.mdx`);
if (!fs.existsSync(filePath)) {
// Try with -2 suffix (common in the dumped files)
filePath = path.join(productsDir, `${fileSlug}-2.mdx`);
}
let product: ProductMdx | null = null;
if (!fs.existsSync(filePath)) {
// Fallback to English if locale is not 'en'
if (locale !== 'en') {
const enProductsDir = path.join(process.cwd(), 'data', 'products', 'en');
let enFilePath = path.join(enProductsDir, `${fileSlug}.mdx`);
if (!fs.existsSync(enFilePath)) {
enFilePath = path.join(enProductsDir, `${fileSlug}-2.mdx`);
}
if (fs.existsSync(enFilePath)) {
const fileContent = fs.readFileSync(enFilePath, 'utf8');
const { data, content } = matter(fileContent);
product = {
slug: fileSlug,
frontmatter: {
...data,
isFallback: true,
} as ProductFrontmatter & { isFallback?: boolean },
content,
};
}
}
} else {
const fileContent = fs.readFileSync(filePath, 'utf8');
const { data, content } = matter(fileContent);
product = {
slug: fileSlug,
frontmatter: data as ProductFrontmatter,
content,
};
}
// Filter out products without images
if (
product &&
(!product.frontmatter.images ||
product.frontmatter.images.length === 0 ||
!product.frontmatter.images[0])
) {
return null;
}
return product;
}
export async function getAllProductSlugs(locale: string): Promise<string[]> {
const productsDir = path.join(process.cwd(), 'data', 'products', locale);
if (!fs.existsSync(productsDir)) return [];
const files = fs.readdirSync(productsDir);
return files.filter((file) => file.endsWith('.mdx')).map((file) => file.replace(/\.mdx$/, ''));
}
export async function getAllProducts(locale: string): Promise<ProductMdx[]> {
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<Partial<ProductMdx>[]> {
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<ProductMdx> => m !== null);
}