Browse Source

优化 swagger

yourname 6 months ago
parent
commit
bce72aa8c8
6 changed files with 99 additions and 67 deletions
  1. 19 18
      src/server/api.ts
  2. 49 0
      src/server/api/base.ts
  3. 5 8
      src/server/index.tsx
  4. 22 0
      src/server/middleware/errorHandler.ts
  5. 4 40
      src/server/swagger.ts
  6. 0 1
      tsconfig.json

+ 19 - 18
src/server/api.ts

@@ -1,22 +1,23 @@
-import { Hono } from 'hono'
-import { z } from 'zod'
-import { zValidator } from '@hono/zod-validator'
+import { OpenAPIHono } from '@hono/zod-openapi'
+import { errorHandler } from './middleware/errorHandler'
+import base from './api/base'
 
-const app = new Hono()
+const app = new OpenAPIHono()
 
-const routes = app.get(
-  '/',
-  zValidator(
-    'query',
-    z.object({
-      name: z.string().optional()
-    })
-  ),
-  (c) => {
-    const { name } = c.req.valid('query')
-    return c.json({ message: `Hello from API${name ? `, ${name}` : ''}` })
+// Register routes
+app.route('/api', base)
+
+// Error handling
+app.onError(errorHandler)
+
+// OpenAPI documentation endpoint
+app.doc('/doc', {
+  openapi: '3.1.0',
+  info: {
+    title: 'API Documentation',
+    version: '1.0.0'
   }
-)
+})
 
-export default routes
-export type AppType = typeof routes
+export default app
+export type AppType = typeof app

+ 49 - 0
src/server/api/base.ts

@@ -0,0 +1,49 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi'
+import { z } from 'zod'
+
+const app = new OpenAPIHono()
+
+const QuerySchema = z.object({
+  name: z.string().optional().openapi({
+    param: {
+      name: 'name',
+      in: 'query'
+    },
+    example: 'John'
+  })
+})
+
+const ResponseSchema = z.object({
+  message: z.string().openapi({
+    example: 'Hello from API, John'
+  })
+})
+
+const route = createRoute({
+  method: 'get',
+  path: '/',
+  request: {
+    query: QuerySchema
+  },
+  responses: {
+    200: {
+      content: {
+        'application/json': {
+          schema: ResponseSchema
+        }
+      },
+      description: 'Successful response'
+    },
+    400: {
+      description: 'Invalid request'
+    }
+  }
+})
+
+app.openapi(route, (c) => {
+  const { name } = c.req.valid('query')
+  return c.json({ message: `Hello from API${name ? `, ${name}` : ''}` })
+})
+
+export default app
+export type BaseAppType = typeof app

+ 5 - 8
src/server/index.tsx

@@ -1,15 +1,12 @@
-import { Hono } from 'hono'
+// import { Hono } from 'hono'
+import { swaggerUI } from '@hono/swagger-ui'
 import { renderer } from './renderer'
-import api from './api'
-import swagger from './swagger'
-
-const app = new Hono()
-
-app.route('/api', api)
-app.route('/swagger', swagger)
+import app from './api'
 
 app.use(renderer)
 
+app.get('/ui', swaggerUI({ url: '/doc' }))
+
 app.get('/*', (c) => {
   return c.render(
     <>

+ 22 - 0
src/server/middleware/errorHandler.ts

@@ -0,0 +1,22 @@
+import { Context } from 'hono'
+import { HTTPException } from 'hono/http-exception'
+
+export const errorHandler = async (err: Error, c: Context) => {
+  if (err instanceof HTTPException) {
+    return c.json(
+      { 
+        error: err.message,
+        status: err.status 
+      },
+      err.status
+    )
+  }
+
+  return c.json(
+    { 
+      error: 'Internal Server Error',
+      status: 500 
+    },
+    500
+  )
+}

+ 4 - 40
src/server/swagger.ts

@@ -1,45 +1,9 @@
-import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi'
+import { Hono } from 'hono'
 import { swaggerUI } from '@hono/swagger-ui'
 
-const app = new OpenAPIHono()
+const app = new Hono()
 
-app.openapi(
-  createRoute({
-    method: 'get',
-    path: '/hello',
-    responses: {
-      200: {
-        description: 'Respond a message',
-        content: {
-          'application/json': {
-            schema: z.object({
-              message: z.string(),
-            }),
-          },
-        },
-      },
-    },
-  }),
-  (c) => {
-    return c.json({
-      message: 'hello',
-    })
-  }
-)
-
-app.get(
-  '/ui',
-  swaggerUI({
-    url: '/swagger/doc',
-  })
-)
-
-app.doc('/doc', {
-  info: {
-    title: 'An API',
-    version: 'v1',
-  },
-  openapi: '3.1.0',
-})
+// Swagger UI endpoint
+app.get('/ui', swaggerUI({ url: '/doc' }))
 
 export default app

+ 0 - 1
tsconfig.json

@@ -11,7 +11,6 @@
       "ESNext"
     ],
     "types": [
-      "@cloudflare/workers-types/2023-07-01",
       "vite/client"
     ],
     "jsx": "react-jsx",