46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import 'server-only';
|
|
import { POSTS, POST_SLUGS, type PostContent } from '@/lib/content/posts';
|
|
import { getSection } from '@/lib/db/store';
|
|
|
|
/**
|
|
* Live blog bodies = in-code `POSTS` defaults overlaid with admin edits.
|
|
*
|
|
* Unlike the `{ fa, en }` section overrides, the blog override stored under the
|
|
* `posts` key is a *partial* map of `slug -> PostContent` holding only the
|
|
* articles that have been edited. Reverting a single article just drops its key
|
|
* from that map, so the in-code default shows through again.
|
|
*/
|
|
|
|
export const POSTS_KEY = 'posts';
|
|
|
|
/** Only the edited articles (empty when nothing has been customized). */
|
|
export function loadPostOverrides(): Record<string, PostContent> {
|
|
try {
|
|
const row = getSection(POSTS_KEY);
|
|
if (row && row.data && typeof row.data === 'object' && !Array.isArray(row.data)) {
|
|
return row.data as Record<string, PostContent>;
|
|
}
|
|
} catch {
|
|
// A missing or locked DB must never crash a public render — defaults only.
|
|
}
|
|
return {};
|
|
}
|
|
|
|
/** Defaults merged with overrides — the full, live article set. */
|
|
export function loadAllPosts(): Record<string, PostContent> {
|
|
return { ...POSTS, ...loadPostOverrides() };
|
|
}
|
|
|
|
export function loadPost(slug: string): PostContent | undefined {
|
|
return loadAllPosts()[slug];
|
|
}
|
|
|
|
export function getPostSlugs(): string[] {
|
|
return Object.keys(loadAllPosts());
|
|
}
|
|
|
|
/** A slug is editable only if it ships with a default (and thus a blog card). */
|
|
export function isKnownSlug(slug: string): boolean {
|
|
return (POST_SLUGS as string[]).includes(slug);
|
|
}
|