132 lines
3.9 KiB
JavaScript
132 lines
3.9 KiB
JavaScript
import { createError, readBody } from 'h3'
|
|
import { z } from 'zod'
|
|
import { requireAdminSession } from '../../../../utils/admin-auth'
|
|
import {
|
|
createPostExportJob,
|
|
queuePostExportJobRun
|
|
} from '../../../../repositories/post-export-repository'
|
|
|
|
const postExportJobInputSchema = z.object({
|
|
dateRangeMode: z.enum(['all', 'year', 'month', 'custom']).optional().default('all'),
|
|
year: z.number().int().min(1970).max(9999).optional(),
|
|
month: z.number().int().min(1).max(12).optional(),
|
|
dateFrom: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
dateTo: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
chunkSize: z.number().int().min(1).max(500).optional(),
|
|
retentionDays: z.number().int().min(1).max(100).optional()
|
|
}).default({})
|
|
|
|
/**
|
|
* KST 기준 날짜 시작 시각을 만든다.
|
|
* @param {string} value - YYYY-MM-DD 날짜
|
|
* @returns {Date} 날짜 시작 시각
|
|
*/
|
|
const createKstDateStart = (value) => new Date(`${value}T00:00:00+09:00`)
|
|
|
|
/**
|
|
* KST 기준 다음 날짜 시작 시각을 만든다.
|
|
* @param {string} value - YYYY-MM-DD 날짜
|
|
* @returns {Date} 다음 날짜 시작 시각
|
|
*/
|
|
const createKstNextDateStart = (value) => {
|
|
const date = createKstDateStart(value)
|
|
date.setUTCDate(date.getUTCDate() + 1)
|
|
return date
|
|
}
|
|
|
|
/**
|
|
* 두 자리 숫자 문자열을 만든다.
|
|
* @param {number} value - 숫자
|
|
* @returns {string} 두 자리 문자열
|
|
*/
|
|
const pad2 = (value) => String(value).padStart(2, '0')
|
|
|
|
/**
|
|
* 요청 입력에서 Export 날짜 범위를 만든다.
|
|
* @param {z.infer<typeof postExportJobInputSchema>} input - 요청 입력
|
|
* @returns {{ dateFrom: Date|null, dateTo: Date|null, rangeLabel: string }} 날짜 범위
|
|
*/
|
|
const createExportDateRange = (input) => {
|
|
if (input.dateRangeMode === 'year') {
|
|
const year = input.year || new Date().getFullYear()
|
|
return {
|
|
dateFrom: createKstDateStart(`${year}-01-01`),
|
|
dateTo: createKstDateStart(`${year + 1}-01-01`),
|
|
rangeLabel: `${year}`
|
|
}
|
|
}
|
|
|
|
if (input.dateRangeMode === 'month') {
|
|
const now = new Date()
|
|
const year = input.year || now.getFullYear()
|
|
const month = input.month || now.getMonth() + 1
|
|
const nextYear = month === 12 ? year + 1 : year
|
|
const nextMonth = month === 12 ? 1 : month + 1
|
|
|
|
return {
|
|
dateFrom: createKstDateStart(`${year}-${pad2(month)}-01`),
|
|
dateTo: createKstDateStart(`${nextYear}-${pad2(nextMonth)}-01`),
|
|
rangeLabel: `${year}-${pad2(month)}`
|
|
}
|
|
}
|
|
|
|
if (input.dateRangeMode === 'custom') {
|
|
if (!input.dateFrom || !input.dateTo) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: '날짜 범위를 선택해 주세요.'
|
|
})
|
|
}
|
|
|
|
const dateFrom = createKstDateStart(input.dateFrom)
|
|
const dateTo = createKstNextDateStart(input.dateTo)
|
|
|
|
if (dateFrom >= dateTo) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: '시작일은 종료일보다 늦을 수 없습니다.'
|
|
})
|
|
}
|
|
|
|
return {
|
|
dateFrom,
|
|
dateTo,
|
|
rangeLabel: `${input.dateFrom}_${input.dateTo}`
|
|
}
|
|
}
|
|
|
|
return {
|
|
dateFrom: null,
|
|
dateTo: null,
|
|
rangeLabel: '전체'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 관리자 게시물 Export 작업 요청 API
|
|
* @param {import('h3').H3Event} event - 요청 이벤트
|
|
* @returns {Promise<Object>} 생성된 Export 작업
|
|
*/
|
|
export default defineEventHandler(async (event) => {
|
|
const adminSession = requireAdminSession(event)
|
|
const input = postExportJobInputSchema.parse(await readBody(event))
|
|
const dateRange = createExportDateRange(input)
|
|
|
|
const job = await createPostExportJob({
|
|
requestedBy: adminSession.userId,
|
|
requestedEmail: adminSession.email,
|
|
scope: 'all',
|
|
dateFrom: dateRange.dateFrom,
|
|
dateTo: dateRange.dateTo,
|
|
rangeLabel: dateRange.rangeLabel,
|
|
chunkSize: input.chunkSize,
|
|
retentionDays: input.retentionDays
|
|
})
|
|
|
|
if (job.status === 'queued') {
|
|
queuePostExportJobRun(job.id)
|
|
}
|
|
|
|
return job
|
|
})
|