hono-api-scaffolder
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseHono API Scaffolder
Hono API 脚手架
Add structured API routes to an existing Cloudflare Workers project. This skill runs AFTER the project shell exists (via cloudflare-worker-builder or vite-flare-starter) and produces route files, middleware, and endpoint documentation.
为已有的Cloudflare Workers项目添加结构化API路由。该工具需在项目框架已通过cloudflare-worker-builder或vite-flare-starter搭建完成后使用,可生成路由文件、中间件以及端点文档。
Workflow
工作流程
Step 1: Gather Endpoints
步骤1:整理端点
Determine what the API needs. Either ask the user or infer from the project description. Group endpoints by resource:
Users: GET /api/users, GET /api/users/:id, POST /api/users, PUT /api/users/:id, DELETE /api/users/:id
Posts: GET /api/posts, GET /api/posts/:id, POST /api/posts, PUT /api/posts/:id
Auth: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me确定API的需求。可询问用户或从项目描述中推断。按资源对端点进行分组:
Users: GET /api/users, GET /api/users/:id, POST /api/users, PUT /api/users/:id, DELETE /api/users/:id
Posts: GET /api/posts, GET /api/posts/:id, POST /api/posts, PUT /api/posts/:id
Auth: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/meStep 2: Create Route Files
步骤2:创建路由文件
One file per resource group. Use the template from assets/route-template.ts:
typescript
// src/routes/users.ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import type { Env } from '../types'
const app = new Hono<{ Bindings: Env }>()
// GET /api/users
app.get('/', async (c) => {
const db = c.env.DB
const { results } = await db.prepare('SELECT * FROM users').all()
return c.json({ users: results })
})
// GET /api/users/:id
app.get('/:id', async (c) => {
const id = c.req.param('id')
const user = await db.prepare('SELECT * FROM users WHERE id = ?').bind(id).first()
if (!user) return c.json({ error: 'Not found' }, 404)
return c.json({ user })
})
// POST /api/users
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
})
app.post('/', zValidator('json', createUserSchema), async (c) => {
const body = c.req.valid('json')
// ... insert logic
return c.json({ user }, 201)
})
export default app每个资源组对应一个文件。使用assets/route-template.ts中的模板:
typescript
// src/routes/users.ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import type { Env } from '../types'
const app = new Hono<{ Bindings: Env }>()
// GET /api/users
app.get('/', async (c) => {
const db = c.env.DB
const { results } = await db.prepare('SELECT * FROM users').all()
return c.json({ users: results })
})
// GET /api/users/:id
app.get('/:id', async (c) => {
const id = c.req.param('id')
const user = await db.prepare('SELECT * FROM users WHERE id = ?').bind(id).first()
if (!user) return c.json({ error: 'Not found' }, 404)
return c.json({ user })
})
// POST /api/users
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
})
app.post('/', zValidator('json', createUserSchema), async (c) => {
const body = c.req.valid('json')
// ... insert logic
return c.json({ user }, 201)
})
export default appStep 3: Add Middleware
步骤3:添加中间件
Based on project needs, add from assets/middleware-template.ts:
Auth middleware — protect routes requiring authentication:
typescript
import { createMiddleware } from 'hono/factory'
import type { Env } from '../types'
export const requireAuth = createMiddleware<{ Bindings: Env }>(async (c, next) => {
const token = c.req.header('Authorization')?.replace('Bearer ', '')
if (!token) return c.json({ error: 'Unauthorized' }, 401)
// Validate token...
await next()
})CORS — use Hono's built-in:
typescript
import { cors } from 'hono/cors'
app.use('/api/*', cors({ origin: ['https://example.com'] }))根据项目需求,从assets/middleware-template.ts中选择添加:
认证中间件 —— 保护需要认证的路由:
typescript
import { createMiddleware } from 'hono/factory'
import type { Env } from '../types'
export const requireAuth = createMiddleware<{ Bindings: Env }>(async (c, next) => {
const token = c.req.header('Authorization')?.replace('Bearer ', '')
if (!token) return c.json({ error: 'Unauthorized' }, 401)
// Validate token...
await next()
})跨域资源共享(CORS) —— 使用Hono内置的功能:
typescript
import { cors } from 'hono/cors'
app.use('/api/*', cors({ origin: ['https://example.com'] }))Step 4: Wire Routes
步骤4:关联路由
Mount all route groups in the main entry point:
typescript
// src/index.ts
import { Hono } from 'hono'
import type { Env } from './types'
import users from './routes/users'
import posts from './routes/posts'
import auth from './routes/auth'
import { errorHandler } from './middleware/error-handler'
const app = new Hono<{ Bindings: Env }>()
// Global error handler
app.onError(errorHandler)
// Mount routes
app.route('/api/users', users)
app.route('/api/posts', posts)
app.route('/api/auth', auth)
// Health check
app.get('/api/health', (c) => c.json({ status: 'ok' }))
export default app在主入口文件中挂载所有路由组:
typescript
// src/index.ts
import { Hono } from 'hono'
import type { Env } from './types'
import users from './routes/users'
import posts from './routes/posts'
import auth from './routes/auth'
import { errorHandler } from './middleware/error-handler'
const app = new Hono<{ Bindings: Env }>()
// 全局错误处理
app.onError(errorHandler)
// 挂载路由
app.route('/api/users', users)
app.route('/api/posts', posts)
app.route('/api/auth', auth)
// 健康检查
app.get('/api/health', (c) => c.json({ status: 'ok' }))
export default appStep 5: Create Types
步骤5:创建类型定义
typescript
// src/types.ts
export interface Env {
DB: D1Database
KV: KVNamespace // if needed
R2: R2Bucket // if needed
API_SECRET: string // secrets
}typescript
// src/types.ts
export interface Env {
DB: D1Database
KV: KVNamespace // if needed
R2: R2Bucket // if needed
API_SECRET: string // secrets
}Step 6: Generate API_ENDPOINTS.md
步骤6:生成API_ENDPOINTS.md
Document all endpoints. See references/endpoint-docs-template.md for the format:
markdown
undefined为所有端点生成文档。格式可参考references/endpoint-docs-template.md:
markdown
undefinedPOST /api/users
POST /api/users
Create a new user.
- Auth: Required (Bearer token)
- Body:
{ name: string, email: string } - Response 201:
{ user: User } - Response 400:
{ error: string, details: ZodError }
undefined创建新用户。
- 认证:需要(Bearer令牌)
- 请求体:
{ name: string, email: string } - 响应201:
{ user: User } - 响应400:
{ error: string, details: ZodError }
undefinedKey Patterns
核心模式
Zod Validation
Zod校验
Always validate request bodies with :
@hono/zod-validatortypescript
import { zValidator } from '@hono/zod-validator'
app.post('/', zValidator('json', schema), async (c) => {
const body = c.req.valid('json') // fully typed
})Install:
pnpm add @hono/zod-validator zod始终使用对请求体进行校验:
@hono/zod-validatortypescript
import { zValidator } from '@hono/zod-validator'
app.post('/', zValidator('json', schema), async (c) => {
const body = c.req.valid('json') // 完全类型化
})安装命令:
pnpm add @hono/zod-validator zodError Handling
错误处理
Use the standard error handler from assets/error-handler.ts:
typescript
export const errorHandler = (err: Error, c: Context) => {
console.error(err)
return c.json({ error: err.message }, 500)
}API routes must return JSON errors, not redirects. follows redirects silently, then the client tries to parse HTML as JSON.
fetch()使用assets/error-handler.ts中的标准错误处理器:
typescript
export const errorHandler = (err: Error, c: Context) => {
console.error(err)
return c.json({ error: err.message }, 500)
}API路由必须返回JSON格式的错误,而非重定向。 会自动跟随重定向,导致客户端尝试将HTML解析为JSON,引发错误。
fetch()RPC Type Safety
RPC类型安全
For end-to-end type safety between Worker and client:
typescript
// Worker: export the app type
export type AppType = typeof app
// Client: use hc (Hono Client)
import { hc } from 'hono/client'
import type { AppType } from '../worker/src/index'
const client = hc<AppType>('https://api.example.com')
const res = await client.api.users.$get() // fully typed实现Worker与客户端之间的端到端类型安全:
typescript
// Worker:导出应用类型
export type AppType = typeof app
// 客户端:使用hc(Hono Client)
import { hc } from 'hono/client'
import type { AppType } from '../worker/src/index'
const client = hc<AppType>('https://api.example.com')
const res = await client.api.users.$get() // 完全类型化Route Groups vs Single File
路由组 vs 单文件
| Project size | Structure |
|---|---|
| < 10 endpoints | Single |
| 10-30 endpoints | Route files per resource ( |
| 30+ endpoints | Route files + shared middleware + typed context |
| 项目规模 | 结构建议 |
|---|---|
| 少于10个端点 | 所有路由放在单个 |
| 10-30个端点 | 按资源拆分路由文件(如 |
| 30个以上端点 | 路由文件 + 共享中间件 + 类型化上下文 |
Reference Files
参考文件
| When | Read |
|---|---|
| Hono patterns, middleware, RPC | references/hono-patterns.md |
| API_ENDPOINTS.md format | references/endpoint-docs-template.md |
| 场景 | 参考文档 |
|---|---|
| Hono模式、中间件、RPC | references/hono-patterns.md |
| API_ENDPOINTS.md格式 | references/endpoint-docs-template.md |
Assets
资源文件
| File | Purpose |
|---|---|
| assets/route-template.ts | Starter route file with CRUD + Zod |
| assets/middleware-template.ts | Auth middleware template |
| assets/error-handler.ts | Standard JSON error handler |
| 文件 | 用途 |
|---|---|
| assets/route-template.ts | 包含CRUD逻辑与Zod校验的路由文件模板 |
| assets/middleware-template.ts | 认证中间件模板 |
| assets/error-handler.ts | 标准JSON错误处理器 |