blog / src /server /services /postService.ts
hadadrjt's picture
blog: Bump to 0.0.5 version.
e99a92f
//
// SPDX-FileCopyrightText: Hadad <hadad@linuxmail.org>
// 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<string, Post> = 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<void> => {
await loadAllPosts();
};
export const loadAllPosts = async (): Promise<void> => {
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<void> => {
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;
};