hono-api-scaffolder

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Hono 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/me

Step 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 app

Step 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 app

Step 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
undefined

POST /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 }
undefined

Key Patterns

核心模式

Zod Validation

Zod校验

Always validate request bodies with
@hono/zod-validator
:
typescript
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-validator
对请求体进行校验:
typescript
import { zValidator } from '@hono/zod-validator'
app.post('/', zValidator('json', schema), async (c) => {
  const body = c.req.valid('json')  // 完全类型化
})
安装命令:
pnpm add @hono/zod-validator zod

Error 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.
fetch()
follows redirects silently, then the client tries to parse HTML as JSON.
使用assets/error-handler.ts中的标准错误处理器:
typescript
export const errorHandler = (err: Error, c: Context) => {
  console.error(err)
  return c.json({ error: err.message }, 500)
}
API路由必须返回JSON格式的错误,而非重定向。
fetch()
会自动跟随重定向,导致客户端尝试将HTML解析为JSON,引发错误。

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 sizeStructure
< 10 endpointsSingle
index.ts
with all routes
10-30 endpointsRoute files per resource (
routes/users.ts
)
30+ endpointsRoute files + shared middleware + typed context
项目规模结构建议
少于10个端点所有路由放在单个
index.ts
文件中
10-30个端点按资源拆分路由文件(如
routes/users.ts
30个以上端点路由文件 + 共享中间件 + 类型化上下文

Reference Files

参考文件

WhenRead
Hono patterns, middleware, RPCreferences/hono-patterns.md
API_ENDPOINTS.md formatreferences/endpoint-docs-template.md
场景参考文档
Hono模式、中间件、RPCreferences/hono-patterns.md
API_ENDPOINTS.md格式references/endpoint-docs-template.md

Assets

资源文件

FilePurpose
assets/route-template.tsStarter route file with CRUD + Zod
assets/middleware-template.tsAuth middleware template
assets/error-handler.tsStandard JSON error handler
文件用途
assets/route-template.ts包含CRUD逻辑与Zod校验的路由文件模板
assets/middleware-template.ts认证中间件模板
assets/error-handler.ts标准JSON错误处理器