Hono Adapter
Seamless integration with Hono framework including automatic route discovery
Hono Adapter
The Hono adapter provides seamless integration with Hono, including automatic route discovery and Zod schema extraction.
Installation
bun add @getvision/adapter-honoBasic Usage
import { Hono } from 'hono'
import { visionAdapter, enableAutoDiscovery } from '@getvision/adapter-hono'
const app = new Hono()
app.use('*', visionAdapter())
enableAutoDiscovery(app)
export default appConfiguration
visionAdapter(options)
interface VisionHonoOptions {
enabled?: boolean // Enable/disable Vision (default: true)
port?: number // Dashboard port (default: 9500)
maxTraces?: number // Max traces to store (default: 1000)
logging?: boolean // Enable console logs (default: true)
// Service metadata
name?: string // Service name (auto-detected from package.json)
service?: {
name?: string
version?: string
description?: string
integrations?: Record<string, string>
}
}Example
app.use('*', visionAdapter({
port: 9500,
maxTraces: 5000,
logging: process.env.NODE_ENV === 'development',
service: {
name: 'my-api',
version: '1.0.0',
description: 'My awesome API',
integrations: {
database: process.env.DATABASE_URL,
redis: process.env.REDIS_URL,
},
},
}))Zod Integration
Use Vision's monkey-patched zValidator to enable automatic schema extraction:
import { zValidator } from '@getvision/adapter-hono'
import { z } from 'zod'
const schema = z.object({
name: z.string().describe('User name'),
email: z.string().email().describe('User email'),
})
app.post('/users', zValidator('json', schema), (c) => {
const data = c.req.valid('json')
// ...
})Vision will automatically:
- Extract the Zod schema
- Generate JSON templates with comments
- Show field types and descriptions in the dashboard
Custom Spans
Track custom operations with useVisionSpan():
import { useVisionSpan } from '@getvision/adapter-hono'
app.get('/users', async (c) => {
const withSpan = useVisionSpan()
// Database query
const users = withSpan('db.query', {
'db.system': 'postgresql',
'db.table': 'users',
}, async () => {
return await db.select().from(users).all()
})
// External API call
const enriched = withSpan('http.request', {
'http.url': 'https://api.example.com/enrich',
'http.method': 'POST',
}, async () => {
return await fetch('https://api.example.com/enrich', {
method: 'POST',
body: JSON.stringify(users),
})
})
return c.json(enriched)
})Response Headers
Vision automatically adds the X-Vision-Trace-Id header to every response. This header contains the unique trace identifier for correlating client-side metrics with server traces.
CORS Required: To read this header in the browser, you must expose it in your CORS configuration:
app.use('*', cors({
origin: '*',
exposeHeaders: ['X-Vision-Trace-Id'],
}))
## Context Access
Get Vision instance and trace ID in your handlers:
```typescript
import { getVisionContext } from '@getvision/adapter-hono'
app.get('/debug', (c) => {
const { vision, traceId } = getVisionContext()
console.log('Current trace:', traceId)
return c.json({ traceId })
})Auto-Discovery
Enable automatic route discovery:
import { enableAutoDiscovery } from '@getvision/adapter-hono'
// After adding visionAdapter middleware
enableAutoDiscovery(app)
// Routes defined after this will be auto-discovered
app.get('/users', handler)
app.post('/users', handler)Vision will automatically detect:
- HTTP methods (GET, POST, PUT, DELETE, etc.)
- Route paths (including dynamic params like
/users/:id) - Handler names
- Zod schemas from
zValidator
Registration Order and Mounted Sub-Apps
- Call
enableAutoDiscovery(app)right aftervisionAdapter()and before you start defining routes. - The adapter now also captures routes of mounted sub-apps via
app.route('/base', child). Define child routes relative to the mount point.
// parent.ts
import { Hono } from 'hono'
import { visionAdapter, enableAutoDiscovery } from '@getvision/adapter-hono'
import analytics from './analytics' // exports a Hono app
const app = new Hono()
app.use('*', visionAdapter())
enableAutoDiscovery(app) // enable first
// define routes and mount sub-apps after discovery is enabled
app.get('/users', handler)
app.route('/analytics', analytics) // child defines '/dashboard' -> becomes '/analytics/dashboard'
export default app// analytics.ts (sub-app)
import { Hono } from 'hono'
const analytics = new Hono()
analytics.get('/dashboard', (c) => c.json({ ok: true }))
export default analyticsDrizzle Studio Integration
Vision can automatically launch Drizzle Studio when configured:
app.use('*', visionAdapter({
drizzle: {
autoStart: true, // Auto-start Drizzle Studio
port: 4983,
},
}))When Drizzle is detected in your project, Vision will:
- Display a Drizzle Studio button in the dashboard
- Auto-start the studio if
autoStart: trueis set - Use the specified port (default: 4983)
Complete Example
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import { z } from 'zod'
import {
visionAdapter,
enableAutoDiscovery,
useVisionSpan,
zValidator
} from '@getvision/adapter-hono'
import { db } from './db'
import { users } from './db/schema'
const app = new Hono()
// Vision setup
app.use('*', visionAdapter({
service: {
name: 'my-api',
version: '1.0.0',
},
}))
enableAutoDiscovery(app)
// Schemas
const createUserSchema = z.object({
name: z.string().min(1).describe('User full name'),
email: z.string().email().describe('User email address'),
})
// Routes
app.get('/users', async (c) => {
const withSpan = useVisionSpan()
const allUsers = withSpan('db.query', {
'db.table': 'users',
}, () => {
return db.select().from(users).all()
})
return c.json(allUsers)
})
app.post('/users',
zValidator('json', createUserSchema),
async (c) => {
const body = c.req.valid('json')
const withSpan = useVisionSpan()
const newUser = withSpan('db.insert', {
'db.table': 'users',
}, () => {
return db.insert(users).values(body).returning().get()
})
return c.json(newUser, 201)
}
)
serve(app)