import db from '@/lib/db/client'; import { ACCESS_TOKEN_COOKIE_NAME } from '@/lib/token'; import { createRoute, z } from '@hono/zod-openapi'; import { deleteCookie } from 'hono/cookie'; import { isNil } from 'lodash'; import { createBodyRequest, createErrorResponse, createErrorResult, createHonoApp, createResponse, paginateTransform, } from '../common/utils'; import { getPostItemRequestSchema, postItemResponseSchema, postPaginateResponseSchema, } from './schema'; import { createPostItem, isSlugUnique } from './service'; const postTags = ['文章操作']; const app = createHonoApp(); export const postApi = app .openapi( createRoute({ tags: postTags, method: 'get', path: '/slug/:slug', request: { params: z.object({ slug: z.string(), }), }, responses: { ...createResponse('请求成功', z.object({ slug: z.string() }).or(z.null()), 200), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const { slug } = c.req.valid('param'); const result = await db.post.findUnique({ where: { slug }, select: { slug: true }, }); return c.json(result, 200); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, ) .openapi( createRoute({ tags: postTags, method: 'get', path: '/', request: { query: z.object({ page: z.coerce.number().optional(), limit: z.coerce.number().optional(), orderby: z.enum(['asc', 'desc']).optional(), }), }, responses: { ...createResponse('请求成功', postPaginateResponseSchema, 200), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const { page, limit, orderby } = c.req.valid('query'); const data = await db.post.paginate( { where: { slug: { not: { equals: null } } }, orderBy: [{ updatedAt: orderby || 'desc' }], }, { page: page || 1, limit: limit || 10, }, ); deleteCookie(c, ACCESS_TOKEN_COOKIE_NAME); const result = paginateTransform(data); return c.json(result, 200); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, ) .openapi( createRoute({ tags: postTags, method: 'get', path: '/page-numbers', request: { query: z.object({ limit: z.coerce.number().optional(), }), }, responses: { ...createResponse('请求成功', z.object({ pageNumbers: z.array(z.number()) }), 200), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const { limit } = c.req.valid('query'); const count = await db.post.count(); const pageNumbers = Math.ceil(count / (limit || 10)); return c.json({ pageNumbers }, 200); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, ) .openapi( createRoute({ tags: postTags, method: 'get', path: '/:item', request: { params: z.object({ item: z.string(), }), }, responses: { ...createResponse('请求成功', postItemResponseSchema, 200), ...createErrorResponse('查询不存在', 404), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const { item } = c.req.valid('param'); const result = await db.post.findFirst({ where: { OR: [ { id: item, }, { slug: item, }, ], }, }); if (isNil(result)) { return c.json(createErrorResult('查询不存在'), 404); } return c.json(result, 200); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, ) .openapi( createRoute({ tags: postTags, method: 'get', path: '/id/:id', request: { params: z.object({ id: z.string(), }), }, responses: { ...createResponse('请求成功', postItemResponseSchema, 200), ...createErrorResponse('参数错误', 404), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const { id } = c.req.valid('param'); const result = await db.post.findUnique({ where: { id }, }); if (!result) { return c.json(createErrorResult('文章不存在'), 404); } return c.json(result, 200); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, ) .openapi( createRoute({ tags: postTags, method: 'delete', path: '/:id', request: { params: z.object({ id: z.string(), }), }, responses: { ...createResponse( '刪除成功', z .object({ msg: z.string(), id: z.string(), }) .or(z.null()), 200, ), ...createErrorResponse('参数错误', 404), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const { id } = c.req.valid('param'); const result = await db.post.delete({ where: { id }, }); console.log(result); if (isNil(result)) { return c.json(createErrorResult('文章不存在'), 404); } return c.json({ msg: '删除成功', id: result.id }, 200); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, ) .openapi( createRoute({ tags: postTags, method: 'post', path: '/', request: { ...createBodyRequest(getPostItemRequestSchema(undefined)), }, responses: { ...createResponse('请求成功', postItemResponseSchema, 200), ...createErrorResponse('参数错误', 400), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const schema = getPostItemRequestSchema(isSlugUnique()); const res = await c.req.json(); const validated = schema.safeParse(res); if (!validated.success) { return c.json( createErrorResult('请求数据验证失败', validated.error.errors), 400, ); } const result = await createPostItem(validated.data); return c.json(result, 201); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, ) .openapi( createRoute({ tags: postTags, method: 'patch', path: '/:id', request: { params: z.object({ id: z.string() }), ...createBodyRequest(getPostItemRequestSchema(undefined)), }, responses: { ...createResponse('请求成功', postItemResponseSchema, 200), ...createErrorResponse('提交失敗', 400), 500: { description: '服务器内部错误' }, }, }), async (c) => { try { const { id } = c.req.valid('param'); const schema = getPostItemRequestSchema(isSlugUnique(id)); const validated = schema.safeParse(await c.req.json()); if (!validated.success) { return c.json( createErrorResult('请求数据验证失败', validated.error.errors), 400, ); } const result = await db.post.update({ where: { id }, data: validated.data, }); return c.json(result, 200); } catch (error) { return c.json(createErrorResult('服务器内部错误', error), 500); } }, );