import { getSamplePageBySlug, getSamplePages, getSamplePostBySlug, getSamplePosts, getSampleTags } from '../utils/sample-content' import { getPostgresClient } from './postgres-client' /** * 게시물 행을 API 응답 구조로 변환 * @param {Object} row - 게시물 행 * @returns {Object} 게시물 응답 */ const mapPostRow = (row) => ({ id: row.id, title: row.title, slug: row.slug, content: row.content, excerpt: row.excerpt, featuredImage: row.featured_image, status: row.status, publishedAt: row.published_at ? row.published_at.toISOString() : null, createdAt: row.created_at.toISOString(), updatedAt: row.updated_at.toISOString(), tags: row.tags || [] }) /** * 고정 페이지 행을 API 응답 구조로 변환 * @param {Object} row - 고정 페이지 행 * @returns {Object} 고정 페이지 응답 */ const mapPageRow = (row) => ({ id: row.id, title: row.title, slug: row.slug, content: row.content, featuredImage: row.featured_image, createdAt: row.created_at.toISOString(), updatedAt: row.updated_at.toISOString() }) /** * 태그 행을 API 응답 구조로 변환 * @param {Object} row - 태그 행 * @returns {Object} 태그 응답 */ const mapTagRow = (row) => ({ id: row.id, name: row.name, slug: row.slug, description: row.description }) /** * 공개 게시물 목록 조회 * @returns {Promise} 게시물 목록 */ export const listPosts = async () => { const sql = getPostgresClient() if (!sql) { return getSamplePosts() } const rows = await sql` SELECT posts.*, COALESCE(array_agg(tags.slug) FILTER (WHERE tags.slug IS NOT NULL), '{}') AS tags FROM posts LEFT JOIN post_tags ON post_tags.post_id = posts.id LEFT JOIN tags ON tags.id = post_tags.tag_id WHERE posts.status = 'published' GROUP BY posts.id ORDER BY posts.published_at DESC NULLS LAST, posts.created_at DESC ` return rows.map(mapPostRow) } /** * 공개 게시물 상세 조회 * @param {string} slug - 게시물 슬러그 * @returns {Promise} 게시물 상세 */ export const getPostBySlug = async (slug) => { const sql = getPostgresClient() if (!sql) { return getSamplePostBySlug(slug) } const rows = await sql` SELECT posts.*, COALESCE(array_agg(tags.slug) FILTER (WHERE tags.slug IS NOT NULL), '{}') AS tags FROM posts LEFT JOIN post_tags ON post_tags.post_id = posts.id LEFT JOIN tags ON tags.id = post_tags.tag_id WHERE posts.slug = ${slug} AND posts.status = 'published' GROUP BY posts.id LIMIT 1 ` return rows[0] ? mapPostRow(rows[0]) : null } /** * 공개 고정 페이지 목록 조회 * @returns {Promise} 고정 페이지 목록 */ export const listPages = async () => { const sql = getPostgresClient() if (!sql) { return getSamplePages() } const rows = await sql` SELECT * FROM pages ORDER BY created_at DESC ` return rows.map(mapPageRow) } /** * 공개 고정 페이지 상세 조회 * @param {string} slug - 페이지 슬러그 * @returns {Promise} 고정 페이지 상세 */ export const getPageBySlug = async (slug) => { const sql = getPostgresClient() if (!sql) { return getSamplePageBySlug(slug) } const rows = await sql` SELECT * FROM pages WHERE slug = ${slug} LIMIT 1 ` return rows[0] ? mapPageRow(rows[0]) : null } /** * 공개 태그 목록 조회 * @returns {Promise} 태그 목록 */ export const listTags = async () => { const sql = getPostgresClient() if (!sql) { return getSampleTags() } const rows = await sql` SELECT * FROM tags ORDER BY name ASC ` return rows.map(mapTagRow) }