import { readFile, readdir } from "fs/promises"; import { join } from "path"; import type { OilForConcernPage, OilForConcernContent, OilsTaxonomyData, ConcernsTaxonomyData, OilTaxonomy, ConcernTaxonomy, LocalizedString, LocalizedSEOKeywords, } from "./types"; const DATA_DIR = join(process.cwd(), "data"); const TAXONOMY_DIR = join(DATA_DIR, "taxonomy"); const CONTENT_DIR = join(DATA_DIR, "content", "oil-for-concern"); let oilsTaxonomyCache: OilsTaxonomyData | null = null; let concernsTaxonomyCache: ConcernsTaxonomyData | null = null; export function getLocalizedString( localized: { sr: string; en: string; de: string; fr: string }, locale: string ): string { return localized[locale as keyof typeof localized] || localized.en; } export function getLocalizedArray( localized: { sr: string[]; en: string[]; de: string[]; fr: string[] }, locale: string ): string[] { return localized[locale as keyof typeof localized] || localized.en; } export function getLocalizedKeywords( seoKeywords: LocalizedSEOKeywords, locale: string ): string[] { const keywords = seoKeywords[locale as keyof LocalizedSEOKeywords] || seoKeywords.en; return [...keywords.primary, ...keywords.secondary, ...keywords.longTail]; } async function getOilsTaxonomy(): Promise { if (oilsTaxonomyCache) return oilsTaxonomyCache; const filePath = join(TAXONOMY_DIR, "oils.json"); const content = await readFile(filePath, "utf-8"); oilsTaxonomyCache = JSON.parse(content) as OilsTaxonomyData; return oilsTaxonomyCache; } async function getConcernsTaxonomy(): Promise { if (concernsTaxonomyCache) return concernsTaxonomyCache; const filePath = join(TAXONOMY_DIR, "concerns.json"); const content = await readFile(filePath, "utf-8"); concernsTaxonomyCache = JSON.parse(content) as ConcernsTaxonomyData; return concernsTaxonomyCache; } async function getOilForConcernContent(oilId: string, concernId: string): Promise { try { const filePath = join(CONTENT_DIR, `${oilId}-${concernId}.json`); const content = await readFile(filePath, "utf-8"); return JSON.parse(content) as OilForConcernContent; } catch (error) { return null; } } function generatePageSlug(oilSlug: string, concernSlug: string, locale: string): string { if (locale === "sr") { return `${oilSlug}-za-${concernSlug}`; } return `${oilSlug}-for-${concernSlug}`; } function generateLocalizedSlugs(oil: OilTaxonomy, concern: ConcernTaxonomy): LocalizedString { return { sr: generatePageSlug(oil.slug.sr, concern.slug.sr, "sr"), en: generatePageSlug(oil.slug.en, concern.slug.en, "en"), de: generatePageSlug(oil.slug.de, concern.slug.de, "de"), fr: generatePageSlug(oil.slug.fr, concern.slug.fr, "fr"), }; } function generatePageTitle(oil: OilTaxonomy, concern: ConcernTaxonomy): LocalizedString { return { sr: `Najbolje ${oil.name.sr.toLowerCase()} za ${concern.name.sr.toLowerCase()}`, en: `Best ${oil.name.en} for ${concern.name.en}`, de: `Bestes ${oil.name.de} für ${concern.name.de}`, fr: `Meilleure ${oil.name.fr.toLowerCase()} pour ${concern.name.fr.toLowerCase()}`, }; } function generateMetaTitle(oil: OilTaxonomy, concern: ConcernTaxonomy): LocalizedString { return { sr: `Najbolje ${oil.name.sr.toLowerCase()} za ${concern.name.sr.toLowerCase()} | Prirodno rešenje | ManoonOils`, en: `Best ${oil.name.en} for ${concern.name.en} | Natural Solution | ManoonOils`, de: `Bestes ${oil.name.de} für ${concern.name.de} | Natürliche Lösung | ManoonOils`, fr: `Meilleure ${oil.name.fr.toLowerCase()} pour ${concern.name.fr.toLowerCase()} | Solution naturelle | ManoonOils`, }; } function generateMetaDescription(oil: OilTaxonomy, concern: ConcernTaxonomy): LocalizedString { return { sr: `Otkrijte zašto je ${oil.name.sr.toLowerCase()} efikasno za ${concern.name.sr.toLowerCase()}. ${oil.shortDescription.sr}`, en: `Discover why ${oil.name.en} is effective for ${concern.name.en}. ${oil.shortDescription.en}`, de: `Entdecken Sie, warum ${oil.name.de} effektiv für ${concern.name.de} ist. ${oil.shortDescription.de}`, fr: `Découvrez pourquoi ${oil.name.fr} est efficace pour ${concern.name.fr}. ${oil.shortDescription.fr}`, }; } async function buildOilForConcernPage( oil: OilTaxonomy, concern: ConcernTaxonomy, content: OilForConcernContent ): Promise { const localizedSlugs = generateLocalizedSlugs(oil, concern); const pageTitle = generatePageTitle(oil, concern); const metaTitle = generateMetaTitle(oil, concern); const metaDescription = generateMetaDescription(oil, concern); return { slug: localizedSlugs.en, localizedSlugs, oilSlug: oil.slug.en, concernSlug: concern.slug.en, oilId: oil.id, concernId: concern.id, pageTitle, metaTitle, metaDescription, oilName: oil.name, concernName: concern.name, whyThisWorks: content.content.whyThisWorks, keyBenefits: content.content.keyBenefits, howToApply: content.content.howToApply, expectedResults: content.content.expectedResults, timeframe: content.content.timeframe, complementaryIngredients: content.metadata.complementaryIngredients, productsToShow: content.metadata.productsToShow, customerResults: content.metadata.customerResults, faqs: content.metadata.faqs, seoKeywords: content.metadata.seoKeywords, relatedPages: content.metadata.relatedPages, }; } export async function getAllOilForConcernPages(): Promise { const [oilsTaxonomy, concernsTaxonomy] = await Promise.all([ getOilsTaxonomy(), getConcernsTaxonomy(), ]); const pages: OilForConcernPage[] = []; for (const oil of Object.values(oilsTaxonomy.oils)) { for (const concernId of oil.concerns) { const concern = concernsTaxonomy.concerns[concernId]; if (!concern) continue; const content = await getOilForConcernContent(oil.id, concernId); if (!content) continue; const page = await buildOilForConcernPage(oil, concern, content); pages.push(page); } } return pages; } export async function getOilForConcernPageBySlug(slug: string, locale: string): Promise { const pages = await getAllOilForConcernPages(); return pages.find(page => page.localizedSlugs[locale as "sr" | "en" | "de" | "fr"] === slug ) || null; } export async function getAllSolutionSlugs(): Promise> { const pages = await getAllOilForConcernPages(); const result: Array<{ locale: string; slug: string }> = []; for (const page of pages) { for (const locale of ["sr", "en", "de", "fr"] as const) { result.push({ locale, slug: page.localizedSlugs[locale] }); } } return result; } export async function getOilForConcernPage(slug: string): Promise { return getOilForConcernPageBySlug(slug, "en"); } export async function getAllOilForConcernSlugs(): Promise { const pages = await getAllOilForConcernPages(); return pages.map(page => page.slug); } export async function getAllOils(): Promise { const taxonomy = await getOilsTaxonomy(); return Object.values(taxonomy.oils); } export async function getAllConcerns(): Promise { const taxonomy = await getConcernsTaxonomy(); return Object.values(taxonomy.concerns); } export async function getOilById(id: string): Promise { const taxonomy = await getOilsTaxonomy(); return taxonomy.oils[id] || null; } export async function getConcernById(id: string): Promise { const taxonomy = await getConcernsTaxonomy(); return taxonomy.concerns[id] || null; } export async function getPagesByOil(oilId: string): Promise { const pages = await getAllOilForConcernPages(); return pages.filter(page => page.oilId === oilId); } export async function getPagesByConcern(concernId: string): Promise { const pages = await getAllOilForConcernPages(); return pages.filter(page => page.concernId === concernId); }