2022-07-01 23:12:47 +02:00
|
|
|
import fs from 'node:fs'
|
|
|
|
import path from 'node:path'
|
2021-11-08 15:10:26 +01:00
|
|
|
|
2023-08-01 17:07:19 +02:00
|
|
|
import { cache } from 'react'
|
2021-11-08 15:10:26 +01:00
|
|
|
import matter from 'gray-matter'
|
2022-02-23 00:38:50 +01:00
|
|
|
|
2023-08-01 17:44:08 +02:00
|
|
|
export const POSTS_PATH = path.join(process.cwd(), 'blog', 'posts')
|
2021-11-08 15:10:26 +01:00
|
|
|
|
|
|
|
export interface FrontMatter {
|
|
|
|
title: string
|
|
|
|
description: string
|
|
|
|
isPublished: boolean
|
|
|
|
publishedOn: string
|
|
|
|
}
|
|
|
|
|
2023-08-01 17:07:19 +02:00
|
|
|
export interface Post {
|
2021-11-08 15:10:26 +01:00
|
|
|
frontmatter: FrontMatter
|
|
|
|
slug: string
|
|
|
|
content: string
|
|
|
|
}
|
|
|
|
|
2023-08-01 17:44:08 +02:00
|
|
|
export const getBlogPosts = cache(async (): Promise<Post[]> => {
|
2022-02-23 00:38:50 +01:00
|
|
|
const posts = await fs.promises.readdir(POSTS_PATH)
|
2021-11-08 15:10:26 +01:00
|
|
|
const postsWithTime = await Promise.all(
|
|
|
|
posts.map(async (postFilename) => {
|
2022-08-27 02:30:55 +02:00
|
|
|
const [slug, extension] = postFilename.split('.')
|
2023-01-10 23:56:46 +01:00
|
|
|
if (slug == null || extension == null) {
|
|
|
|
throw new Error('Invalid postFilename.')
|
|
|
|
}
|
2022-08-27 02:30:55 +02:00
|
|
|
const blogPostPath = path.join(POSTS_PATH, `${slug}.${extension}`)
|
2021-11-08 15:10:26 +01:00
|
|
|
const blogPostContent = await fs.promises.readFile(blogPostPath, {
|
|
|
|
encoding: 'utf8'
|
|
|
|
})
|
2023-05-21 14:42:53 +02:00
|
|
|
const { data, content } = matter(blogPostContent) as unknown as {
|
|
|
|
data: FrontMatter
|
|
|
|
content: string
|
|
|
|
}
|
2021-11-08 15:10:26 +01:00
|
|
|
const date = new Date(data.publishedOn)
|
|
|
|
return {
|
|
|
|
slug,
|
|
|
|
content,
|
|
|
|
frontmatter: data,
|
|
|
|
time: date.getTime()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
|
|
|
const postsWithTimeSorted = postsWithTime
|
2022-09-04 20:40:58 +02:00
|
|
|
.filter((post) => {
|
|
|
|
return post.frontmatter.isPublished
|
|
|
|
})
|
|
|
|
.sort((a, b) => {
|
|
|
|
return b.time - a.time
|
|
|
|
})
|
2021-11-08 15:10:26 +01:00
|
|
|
return postsWithTimeSorted
|
2023-08-01 17:07:19 +02:00
|
|
|
})
|
2021-11-08 15:10:26 +01:00
|
|
|
|
2023-08-01 17:44:08 +02:00
|
|
|
export const getBlogPostBySlug = cache(
|
2023-08-01 17:07:19 +02:00
|
|
|
async (slug: string): Promise<Post | undefined> => {
|
2023-08-01 17:44:08 +02:00
|
|
|
const posts = await getBlogPosts()
|
2023-08-01 17:07:19 +02:00
|
|
|
const post = posts.find((post) => {
|
|
|
|
return post.slug === slug
|
|
|
|
})
|
|
|
|
return post
|
2021-11-08 15:10:26 +01:00
|
|
|
}
|
2023-08-01 17:07:19 +02:00
|
|
|
)
|