// // SPDX-FileCopyrightText: Hadad // SPDX-License-Identifier: Apache-2.0 // import { readdir, readFile, stat } from "fs/promises"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; import { parseMarkdown, extractFrontMatter } from "../utils/markdownParser.js"; import { siteConfig } from "../../shared/config.js"; import type { Post, PostSummary } from "../../shared/types.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const POSTS_DIRECTORY = join(__dirname, "../../../", siteConfig.files.postsDirectoryName); const postsCache: Map = new Map(); const isMarkdownFile = (filename: string): boolean => { return siteConfig.files.markdownExtensionPattern.test(filename); }; const extractSlugFromFilename = (filename: string): string => { return filename.replace(siteConfig.files.markdownExtensionPattern, ""); }; const compareDateDescending = (a: PostSummary, b: PostSummary): number => { return new Date(b.frontMatter.date).getTime() - new Date(a.frontMatter.date).getTime(); }; const postToSummary = (post: Post): PostSummary => ({ slug: post.slug, frontMatter: post.frontMatter, lastModified: post.lastModified, }); export const getPostsDirectory = (): string => { return POSTS_DIRECTORY; }; export const initializePostService = async (): Promise => { await loadAllPosts(); }; export const loadAllPosts = async (): Promise => { try { const files = await readdir(POSTS_DIRECTORY); const markdownFiles = files.filter(isMarkdownFile); postsCache.clear(); for (const file of markdownFiles) { await loadPost(file); } console.log(siteConfig.logs.postsLoaded(postsCache.size)); } catch (error) { console.error(siteConfig.errors.loadingPosts(error)); } }; export const loadPost = async (filename: string): Promise => { try { const filePath = join(POSTS_DIRECTORY, filename); const [fileContent, fileStat] = await Promise.all([ readFile(filePath, "utf-8"), stat(filePath), ]); const slug = extractSlugFromFilename(filename); const post: Post = { slug, frontMatter: extractFrontMatter(fileContent), content: parseMarkdown(fileContent), rawContent: fileContent, lastModified: fileStat.mtimeMs, }; postsCache.set(slug, post); } catch (error) { console.error(siteConfig.errors.loadingPost(filename, error)); } }; export const removePost = (filename: string): void => { const slug = extractSlugFromFilename(filename); postsCache.delete(slug); console.log(siteConfig.logs.postRemoved(slug)); }; export const getAllPosts = (): PostSummary[] => { return Array.from(postsCache.values()).map(postToSummary).sort(compareDateDescending); }; export const getPostBySlug = (slug: string): Post | null => { return postsCache.get(slug) || null; };