// The one read path. Every page, the feed, the sitemap and the llms.txt call // these, and nothing else reads the posts table. import { getDb } from "@/db/client"; import { posts } from "@/db/schema"; import { and, desc, eq, isNotNull } from "drizzle-orm"; import { cacheLife, cacheTag } from "next/cache"; import { rowToPost } from "./rows"; import type { Post, PostSummary } from "./schema"; export const BLOG_TAG = "blog"; const published = and(eq(posts.draft, false), isNotNull(posts.publishedAt)); /** Every published post with its body, newest first. */ export async function listPublishedPostsWithBody(): Promise { "use cache"; cacheTag(BLOG_TAG); cacheLife("max"); const rows = await getDb() .select() .from(posts) .where(published) .orderBy(desc(posts.publishedAt), posts.slug); return rows.map(rowToPost); } /** Every published post without its body, newest first. */ export async function listPublishedPosts(): Promise { "use cache"; cacheTag(BLOG_TAG); cacheLife("max"); const all = await listPublishedPostsWithBody(); return all.map((post) => { const summary: PostSummary & { body?: string } = { ...post }; delete summary.body; return summary; }); } export async function getPublishedPost(slug: string): Promise { "use cache"; cacheTag(BLOG_TAG); cacheLife("max"); const [row] = await getDb() .select() .from(posts) .where(and(published, eq(posts.slug, slug))) .limit(1); return row ? rowToPost(row) : null; }