사이트 설정 관리 추가
This commit is contained in:
7
server/api/site-settings.get.js
Normal file
7
server/api/site-settings.get.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { getSiteSettings } from '../repositories/content-repository'
|
||||
|
||||
/**
|
||||
* 공개 사이트 설정 API
|
||||
* @returns {Promise<Object>} 사이트 설정
|
||||
*/
|
||||
export default defineEventHandler(() => getSiteSettings())
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
getSamplePosts,
|
||||
getSampleTags
|
||||
} from '../utils/sample-content'
|
||||
import { getDefaultSiteSettings } from '../utils/site-settings'
|
||||
import { getPostgresClient } from './postgres-client'
|
||||
|
||||
/**
|
||||
@@ -55,6 +56,20 @@ const mapTagRow = (row) => ({
|
||||
color: row.color
|
||||
})
|
||||
|
||||
/**
|
||||
* 사이트 설정 행을 API 응답 구조로 변환
|
||||
* @param {Object} row - 사이트 설정 행
|
||||
* @returns {Object} 사이트 설정 응답
|
||||
*/
|
||||
const mapSiteSettingsRow = (row) => ({
|
||||
title: row.title,
|
||||
description: row.description,
|
||||
siteUrl: row.site_url,
|
||||
logoText: row.logo_text,
|
||||
copyrightText: row.copyright_text,
|
||||
updatedAt: row.updated_at.toISOString()
|
||||
})
|
||||
|
||||
/**
|
||||
* 태그 슬러그 목록 정규화
|
||||
* @param {Array<string>} tags - 태그 슬러그 목록
|
||||
@@ -488,6 +503,72 @@ export const listTags = async () => {
|
||||
return rows.map(mapTagRow)
|
||||
}
|
||||
|
||||
/**
|
||||
* 사이트 설정 조회
|
||||
* @returns {Promise<Object>} 사이트 설정
|
||||
*/
|
||||
export const getSiteSettings = async () => {
|
||||
const sql = getPostgresClient()
|
||||
|
||||
if (!sql) {
|
||||
return getDefaultSiteSettings()
|
||||
}
|
||||
|
||||
const rows = await sql`
|
||||
SELECT *
|
||||
FROM site_settings
|
||||
WHERE id = 1
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
return rows[0] ? mapSiteSettingsRow(rows[0]) : getDefaultSiteSettings()
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 사이트 설정 수정
|
||||
* @param {Object} input - 사이트 설정 입력값
|
||||
* @returns {Promise<Object>} 수정된 사이트 설정
|
||||
*/
|
||||
export const updateSiteSettings = async (input) => {
|
||||
const sql = getPostgresClient()
|
||||
|
||||
if (!sql) {
|
||||
throw new Error('DATABASE_REQUIRED')
|
||||
}
|
||||
|
||||
const rows = await sql`
|
||||
INSERT INTO site_settings (
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
site_url,
|
||||
logo_text,
|
||||
copyright_text,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
${input.title},
|
||||
${input.description},
|
||||
${input.siteUrl},
|
||||
${input.logoText},
|
||||
${input.copyrightText},
|
||||
now()
|
||||
)
|
||||
ON CONFLICT (id) DO UPDATE
|
||||
SET
|
||||
title = EXCLUDED.title,
|
||||
description = EXCLUDED.description,
|
||||
site_url = EXCLUDED.site_url,
|
||||
logo_text = EXCLUDED.logo_text,
|
||||
copyright_text = EXCLUDED.copyright_text,
|
||||
updated_at = now()
|
||||
RETURNING *
|
||||
`
|
||||
|
||||
return mapSiteSettingsRow(rows[0])
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 태그 상세 조회
|
||||
* @param {string} id - 태그 ID
|
||||
|
||||
13
server/routes/admin/api/settings.get.js
Normal file
13
server/routes/admin/api/settings.get.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { requireAdminSession } from '../../../utils/admin-auth'
|
||||
import { getSiteSettings } from '../../../repositories/content-repository'
|
||||
|
||||
/**
|
||||
* 관리자 사이트 설정 조회 API
|
||||
* @param {import('h3').H3Event} event - 요청 이벤트
|
||||
* @returns {Promise<Object>} 사이트 설정
|
||||
*/
|
||||
export default defineEventHandler((event) => {
|
||||
requireAdminSession(event)
|
||||
|
||||
return getSiteSettings()
|
||||
})
|
||||
24
server/routes/admin/api/settings.put.js
Normal file
24
server/routes/admin/api/settings.put.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { createError, readBody } from 'h3'
|
||||
import { requireAdminSession } from '../../../utils/admin-auth'
|
||||
import { parseAdminSiteSettingsInput } from '../../../utils/admin-site-settings-input'
|
||||
import { updateSiteSettings } from '../../../repositories/content-repository'
|
||||
|
||||
/**
|
||||
* 관리자 사이트 설정 수정 API
|
||||
* @param {import('h3').H3Event} event - 요청 이벤트
|
||||
* @returns {Promise<Object>} 수정된 사이트 설정
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
requireAdminSession(event)
|
||||
|
||||
const parsedBody = parseAdminSiteSettingsInput(await readBody(event))
|
||||
|
||||
if (!parsedBody.success) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
message: '사이트 설정 입력 형식이 올바르지 않습니다.'
|
||||
})
|
||||
}
|
||||
|
||||
return updateSiteSettings(parsedBody.data)
|
||||
})
|
||||
16
server/utils/admin-site-settings-input.js
Normal file
16
server/utils/admin-site-settings-input.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const adminSiteSettingsInputSchema = z.object({
|
||||
title: z.string().trim().min(1),
|
||||
description: z.string().trim().default(''),
|
||||
siteUrl: z.string().trim().url(),
|
||||
logoText: z.string().trim().min(1).max(8),
|
||||
copyrightText: z.string().trim().min(1)
|
||||
})
|
||||
|
||||
/**
|
||||
* 관리자 사이트 설정 입력값 정리
|
||||
* @param {unknown} body - 요청 본문
|
||||
* @returns {import('zod').SafeParseReturnType<unknown, Object>} 검증 결과
|
||||
*/
|
||||
export const parseAdminSiteSettingsInput = (body) => adminSiteSettingsInputSchema.safeParse(body)
|
||||
17
server/utils/site-settings.js
Normal file
17
server/utils/site-settings.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 기본 사이트 설정 반환
|
||||
* @returns {Object} 기본 사이트 설정
|
||||
*/
|
||||
export const getDefaultSiteSettings = () => {
|
||||
const config = useRuntimeConfig()
|
||||
const title = config.public.siteTitle || 'sori.studio'
|
||||
|
||||
return {
|
||||
title,
|
||||
description: 'sori.studio 개인 블로그',
|
||||
siteUrl: config.public.siteUrl || 'https://sori.studio',
|
||||
logoText: '井',
|
||||
copyrightText: `©${new Date().getFullYear()} ${title}`,
|
||||
updatedAt: null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user