api.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { OpenAPIHono } from '@hono/zod-openapi'
  2. import { swaggerUI } from '@hono/swagger-ui'
  3. import { errorHandler } from './utils/errorHandler'
  4. import usersRouter from './api/users/index'
  5. import authRoute from './api/auth/index'
  6. import rolesRoute from './api/roles/index'
  7. import fileRoutes from './api/files/index'
  8. import { AuthContext } from './types/context'
  9. import { AppDataSource } from './data-source'
  10. import { Hono } from 'hono'
  11. const app = new Hono();
  12. const api = new OpenAPIHono<AuthContext>()
  13. api.onError(errorHandler)
  14. // Rate limiting
  15. api.use('/api/v1/*', async (c, next) => {
  16. const ip = c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip')
  17. // 实现速率限制逻辑
  18. await next()
  19. })
  20. // 数据库初始化中间件
  21. api.use('/api/v1/*', async (c, next) => {
  22. if(!AppDataSource.isInitialized) {
  23. await AppDataSource.initialize();
  24. }
  25. await next();
  26. })
  27. // 注册Bearer认证方案
  28. api.openAPIRegistry.registerComponent('securitySchemes','bearerAuth',{
  29. type:'http',
  30. scheme:'bearer',
  31. bearerFormat:'JWT',
  32. description:'使用JWT进行认证'
  33. })
  34. // OpenAPI documentation endpoint
  35. // !import.meta.env.PROD
  36. if(1){
  37. // api.doc31('/doc', {
  38. // openapi: '3.1.0',
  39. // info: {
  40. // title: 'API Documentation',
  41. // version: '1.0.0'
  42. // },
  43. // security: [{
  44. // bearerAuth: []
  45. // }]
  46. // // servers: [{ url: '/api/v1' }]
  47. // })
  48. api.get('/doc', (c) => {
  49. const config = {
  50. openapi: '3.1.0',
  51. info: {
  52. title: 'API Documentation',
  53. version: '1.0.0'
  54. },
  55. security: [{
  56. bearerAuth: []
  57. }]
  58. // servers: [{ url: '/api/v1' }]
  59. };
  60. try {
  61. const document = api.getOpenAPI31Document(config);
  62. return c.json(document);
  63. } catch (e: any) {
  64. return c.json({
  65. error: 'OpenAPI document generation failed',
  66. message: e.message || 'Unknown error',
  67. stack: e.stack
  68. }, 500)
  69. }
  70. })
  71. app.get('/ui', swaggerUI({
  72. url: '/doc',
  73. persistAuthorization: true,
  74. manuallySwaggerUIHtml: (asset) => `
  75. <div>
  76. <div id="swagger-ui"></div>
  77. <link rel="stylesheet" href="https://ai-oss.d8d.fun/swagger-ui-dist/swagger-ui.css" />
  78. <script src="https://ai-oss.d8d.fun/swagger-ui-dist/swagger-ui-bundle.js" crossorigin="anonymous"></script>
  79. <script>
  80. window.onload = () => {
  81. window.ui = SwaggerUIBundle({
  82. dom_id: '#swagger-ui',
  83. url: '/doc',
  84. persistAuthorization: true
  85. })
  86. }
  87. </script>
  88. </div>
  89. `
  90. }))
  91. }
  92. const userRoutes = api.route('/api/v1/users', usersRouter)
  93. const authRoutes = api.route('/api/v1/auth', authRoute)
  94. const roleRoutes = api.route('/api/v1/roles', rolesRoute)
  95. const fileApiRoutes = api.route('/api/v1/files', fileRoutes)
  96. export type AuthRoutes = typeof authRoutes
  97. export type UserRoutes = typeof userRoutes
  98. export type RoleRoutes = typeof roleRoutes
  99. export type FileRoutes = typeof fileApiRoutes
  100. app.route('/', api)
  101. export default app