import { requireAdminSession } from '../../../../utils/admin-auth' import { getBackupStorageSummary } from '../../../../utils/backup-storage-summary' import { getPostgresClient } from '../../../../repositories/postgres-client' /** * 빈 콘텐츠 집계를 만든다. * @returns {Object} 콘텐츠 집계 */ const createEmptyContentSummary = () => ({ posts: { total: 0, published: 0, draft: 0, private: 0, members: 0, scheduled: 0 }, pages: { total: 0, published: 0, draft: 0, private: 0, listed: 0, featured: 0 }, tags: { total: 0, managed: 0, general: 0, used: 0 }, comments: { total: 0, published: 0, pending: 0, blocked: 0 }, members: { total: 0, owner: 0, admin: 0, member: 0 } }) /** * 숫자 값을 안전하게 정수로 변환한다. * @param {unknown} value - 원본 값 * @returns {number} 정수 값 */ const toCount = (value) => Number(value || 0) /** * 백업 점검용 콘텐츠 수량 집계를 조회한다. * @returns {Promise} 콘텐츠 수량 집계 */ const getBackupContentSummary = async () => { const sql = getPostgresClient() if (!sql) { return createEmptyContentSummary() } const rows = await sql` SELECT (SELECT COUNT(*)::int FROM posts) AS "postsTotal", (SELECT COUNT(*)::int FROM posts WHERE status = 'published') AS "postsPublished", (SELECT COUNT(*)::int FROM posts WHERE status = 'draft') AS "postsDraft", (SELECT COUNT(*)::int FROM posts WHERE status = 'private') AS "postsPrivate", (SELECT COUNT(*)::int FROM posts WHERE status = 'members') AS "postsMembers", (SELECT COUNT(*)::int FROM posts WHERE status IN ('published', 'members') AND published_at > now()) AS "postsScheduled", (SELECT COUNT(*)::int FROM pages) AS "pagesTotal", (SELECT COUNT(*)::int FROM pages WHERE status = 'published') AS "pagesPublished", (SELECT COUNT(*)::int FROM pages WHERE status = 'draft') AS "pagesDraft", (SELECT COUNT(*)::int FROM pages WHERE status = 'private') AS "pagesPrivate", (SELECT COUNT(*)::int FROM pages WHERE is_listed = true) AS "pagesListed", (SELECT COUNT(*)::int FROM pages WHERE is_featured = true) AS "pagesFeatured", (SELECT COUNT(*)::int FROM tags) AS "tagsTotal", (SELECT COUNT(*)::int FROM tags WHERE tag_type = 'managed') AS "tagsManaged", (SELECT COUNT(*)::int FROM tags WHERE tag_type = 'general') AS "tagsGeneral", (SELECT COUNT(DISTINCT tag_id)::int FROM post_tags) AS "tagsUsed", (SELECT COUNT(*)::int FROM comments) AS "commentsTotal", (SELECT COUNT(*)::int FROM comments WHERE status = 'published') AS "commentsPublished", (SELECT COUNT(*)::int FROM comments WHERE status = 'pending') AS "commentsPending", (SELECT COUNT(*)::int FROM comments WHERE status = 'blocked') AS "commentsBlocked", (SELECT COUNT(*)::int FROM users) AS "membersTotal", (SELECT COUNT(*)::int FROM users WHERE user_role = 'owner') AS "membersOwner", (SELECT COUNT(*)::int FROM users WHERE user_role = 'admin') AS "membersAdmin", (SELECT COUNT(*)::int FROM users WHERE user_role = 'member') AS "membersMember" ` const row = rows[0] || {} return { posts: { total: toCount(row.postsTotal), published: toCount(row.postsPublished), draft: toCount(row.postsDraft), private: toCount(row.postsPrivate), members: toCount(row.postsMembers), scheduled: toCount(row.postsScheduled) }, pages: { total: toCount(row.pagesTotal), published: toCount(row.pagesPublished), draft: toCount(row.pagesDraft), private: toCount(row.pagesPrivate), listed: toCount(row.pagesListed), featured: toCount(row.pagesFeatured) }, tags: { total: toCount(row.tagsTotal), managed: toCount(row.tagsManaged), general: toCount(row.tagsGeneral), used: toCount(row.tagsUsed) }, comments: { total: toCount(row.commentsTotal), published: toCount(row.commentsPublished), pending: toCount(row.commentsPending), blocked: toCount(row.commentsBlocked) }, members: { total: toCount(row.membersTotal), owner: toCount(row.membersOwner), admin: toCount(row.membersAdmin), member: toCount(row.membersMember) } } } /** * 관리자 사이트 용량 조회 API * @param {import('h3').H3Event} event - 요청 이벤트 * @returns {Promise} 백업 점검용 현황 */ export default defineEventHandler(async (event) => { requireAdminSession(event) const [content, storage] = await Promise.all([ getBackupContentSummary(), getBackupStorageSummary() ]) return { generatedAt: new Date().toISOString(), content, storage } })