import { z } from 'zod'
// 确保 fetch 可用 (Node.js 18+)
if (typeof globalThis.fetch === 'undefined') {
throw new Error('fetch is not available. Please use Node.js 18 or later.')
}
/**
* 博客文章数据验证模式
*/
export const BlogPostSchema = z.object({
title: z.string().min(1, '标题不能为空'),
description: z.string().min(1, '描述不能为空'),
content: z.string().min(1, '内容不能为空'),
slug: z.string().min(1, 'URL 地址不能为空'),
status: z.enum(['draft', 'published']).default('draft'),
cover_url: z.url('封面图片 URL 格式不正确').default('https://example.com/cover.jpg'),
author_name: z.string().default('Lafe'),
author_avatar_url: z.url('作者头像 URL 格式不正确').default('https://example.com/avatar.jpg'),
locale: z.string().default('en'),
})
/**
* 博客文章类型
*/
export type BlogPost = z.infer<typeof BlogPostSchema>
/**
* API 响应类型
*/
export interface BlogApiResponse {
success: boolean
msg?: any
errMsg?: string
}
/**
* CMS 博客客户端
* 用于对接 CMS 博客系统 API
*/
export class CMSBlogClient {
private readonly apiUrl: string
/**
* 创建 CMS 博客客户端
* @param apiUrl - CMS 博客系统的 API URL
*/
constructor(apiUrl: string = 'https://cms.qmiai.net/api/veegen') {
this.apiUrl = apiUrl
}
/**
* 发布博客文章
* @param blogData - 博客文章数据
* @returns API 响应结果
*/
async postBlog(blogData: Partial<BlogPost>): Promise<BlogApiResponse> {
try {
// 使用 Zod 验证和标准化数据
const validatedData = BlogPostSchema.parse(blogData)
console.log('Posting blog with data:', validatedData)
const response = await fetch(`${this.apiUrl}/blog`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(validatedData),
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`)
}
const result = (await response.json()) as BlogApiResponse
if (!result.success) {
throw new Error(`API error: ${result.errMsg || 'Unknown error'}`)
}
return result
} catch (error) {
if (error instanceof z.ZodError) {
// 处理验证错误
const errorMessages = error.issues.map((err: any) => `${err.path.join('.')}: ${err.message}`).join(', ')
throw new Error(`数据验证失败: ${errorMessages}`)
}
console.error('Failed to post blog:', error)
throw error
}
}
/**
* 验证博客数据
* @param blogData - 要验证的博客数据
* @returns 验证结果
*/
validateBlogData(blogData: any): { success: boolean; data?: BlogPost; errors?: string[] } {
try {
const validatedData = BlogPostSchema.parse(blogData)
return { success: true, data: validatedData }
} catch (error) {
if (error instanceof z.ZodError) {
const errors = error.issues.map((err: any) => `${err.path.join('.')}: ${err.message}`)
return { success: false, errors }
}
return { success: false, errors: ['未知验证错误'] }
}
}
}