The Factory Helper provides utilities for creating type-safe Hono applications, middleware, and handlers with proper type inference.
Import
import { createFactory, createMiddleware } from 'hono/factory'
import { Factory } from 'hono/factory'
Functions
createFactory()
Creates a factory instance for creating type-safe Hono components.
function createFactory<E extends Env = Env, P extends string = string>(init?: {
initApp?: InitApp<E>
defaultAppOptions?: HonoOptions<E>
}): Factory<E, P>
Optional function to initialize new app instances
Default options for created apps
A factory instance with methods for creating apps, middleware, and handlers
Example
import { createFactory } from 'hono/factory'
// Create a factory with environment types
type Env = {
Bindings: {
DB: Database
API_KEY: string
}
Variables: {
user: User
}
}
const factory = createFactory<Env>()
createMiddleware()
Creates type-safe middleware without needing a factory instance.
function createMiddleware<
E extends Env = any,
P extends string = string,
I extends Input = {},
R extends HandlerResponse<any> | void = void
>(
middleware: MiddlewareHandler<E, P, I, R extends void ? Response : R>
): MiddlewareHandler<E, P, I, R extends void ? Response : R>
middleware
MiddlewareHandler
required
The middleware handler function
The same middleware with proper type inference
Example
import { createMiddleware } from 'hono/factory'
const logger = createMiddleware(async (c, next) => {
console.log(`[${c.req.method}] ${c.req.url}`)
await next()
})
app.use(logger)
Factory Methods
factory.createApp()
Creates a new Hono application instance.
factory.createApp(options?: HonoOptions<E>): Hono<E>
Options for the Hono app (merged with default options)
A new Hono application instance
Example
const factory = createFactory<Env>({
initApp: (app) => {
// Initialize all apps with common middleware
app.use('*', logger())
},
defaultAppOptions: {
strict: false
}
})
const app = factory.createApp()
const apiApp = factory.createApp({ strict: true })
factory.createMiddleware()
Creates type-safe middleware with the factory’s environment types.
factory.createMiddleware<I extends Input = {}, R extends HandlerResponse<any> | void = void>(
middleware: MiddlewareHandler<E, P, I, R extends void ? Response : R>
): MiddlewareHandler<E, P, I, R extends void ? Response : R>
middleware
MiddlewareHandler
required
The middleware handler function
Example
type Env = {
Bindings: {
DB: Database
}
Variables: {
user: User
}
}
const factory = createFactory<Env>()
const authMiddleware = factory.createMiddleware(async (c, next) => {
const token = c.req.header('Authorization')
if (!token) {
return c.text('Unauthorized', 401)
}
const user = await verifyToken(token, c.env.DB)
c.set('user', user) // Type-safe: user must match Env.Variables.user
await next()
})
app.use(authMiddleware)
factory.createHandlers()
Creates an array of type-safe handlers.
factory.createHandlers(...handlers: H[]): H[]
Variable number of handler functions
Array of handlers with proper type inference
Example
const factory = createFactory<Env>()
const handlers = factory.createHandlers(
// Middleware
async (c, next) => {
console.log('Before')
await next()
console.log('After')
},
// Handler
(c) => {
const user = c.get('user') // Type-safe
return c.json({ user })
}
)
app.get('/profile', ...handlers)
Examples
Basic Factory Usage
import { createFactory } from 'hono/factory'
import type { User, Database } from './types'
type Env = {
Bindings: {
DB: Database
}
Variables: {
user: User
}
}
const factory = createFactory<Env>()
// Create middleware
const authMiddleware = factory.createMiddleware(async (c, next) => {
const user = await authenticate(c.req.header('Authorization'))
c.set('user', user)
await next()
})
// Create handlers
const getUser = factory.createHandlers(
authMiddleware,
(c) => {
const user = c.get('user')
return c.json(user)
}
)
const app = factory.createApp()
app.get('/user', ...getUser)
Reusable Middleware Factory
import { createFactory } from 'hono/factory'
type Env = {
Variables: {
requestId: string
}
}
const factory = createFactory<Env>()
// Create a reusable middleware generator
function createRequestId() {
return factory.createMiddleware(async (c, next) => {
c.set('requestId', crypto.randomUUID())
await next()
})
}
const app = factory.createApp()
app.use('*', createRequestId())
app.get('/', (c) => {
const requestId = c.get('requestId') // Type-safe
return c.json({ requestId })
})
Modular App Structure
// factories/app.ts
import { createFactory } from 'hono/factory'
import { logger } from 'hono/logger'
export type AppEnv = {
Bindings: {
DB: Database
}
Variables: {
user: User | null
}
}
export const factory = createFactory<AppEnv>({
initApp: (app) => {
app.use('*', logger())
}
})
// middleware/auth.ts
import { factory } from '../factories/app'
export const authMiddleware = factory.createMiddleware(async (c, next) => {
const user = await getUser(c.req.header('Authorization'))
c.set('user', user)
await next()
})
// routes/users.ts
import { factory } from '../factories/app'
import { authMiddleware } from '../middleware/auth'
const userHandlers = factory.createHandlers(
authMiddleware,
(c) => {
const user = c.get('user')
return c.json({ user })
}
)
export const userRoutes = factory.createApp()
userRoutes.get('/', ...userHandlers)
// app.ts
import { factory } from './factories/app'
import { userRoutes } from './routes/users'
const app = factory.createApp()
app.route('/users', userRoutes)
import { createFactory } from 'hono/factory'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
const factory = createFactory()
const schema = z.object({
name: z.string(),
age: z.number()
})
const handlers = factory.createHandlers(
zValidator('json', schema),
(c) => {
const data = c.req.valid('json') // Type is inferred
return c.json({ message: `Hello ${data.name}` })
}
)
app.post('/create', ...handlers)
Benefits
Type Safety
The factory ensures all components share the same environment types:
const factory = createFactory<Env>()
// All created components have access to Env types
const middleware = factory.createMiddleware(async (c, next) => {
c.env.DB // ✓ Type-safe
c.get('user') // ✓ Type-safe
await next()
})
Reusability
Create reusable middleware and handlers:
function createAuthMiddleware(requiredRole: string) {
return factory.createMiddleware(async (c, next) => {
const user = c.get('user')
if (user.role !== requiredRole) {
return c.text('Forbidden', 403)
}
await next()
})
}
app.get('/admin', createAuthMiddleware('admin'), (c) => {
return c.text('Admin panel')
})
Consistent Setup
Initialize all apps with common configuration:
const factory = createFactory<Env>({
initApp: (app) => {
app.use('*', logger())
app.use('*', cors())
}
})
// All apps automatically have logger and cors
const app1 = factory.createApp()
const app2 = factory.createApp()