Skip to content
Open
34 changes: 34 additions & 0 deletions .changeset/quiet-snakes-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
'@hono/zod-openapi': minor
---

This PR adds two new utilities to improve route definition and registration in `@hono/zod-openapi`:

- `defineOpenAPIRoute`: Provides explicit type safety for route definitions
- `openapiRoutes`: Enables batch registration of multiple routes with full type safety

- Registering many routes individually was repetitive and verbose
- Type inference for complex route configurations was challenging
- Organizing routes across multiple files was difficult
- No built-in support for conditional route registration
- RPC type safety was hard to maintain across scattered route registrations

- `defineOpenAPIRoute`: Wraps route definitions with explicit types for better IDE support and type checking
- `openapiRoutes`: Accepts an array of route definitions and registers them all at once
- Supports `addRoute` flag for conditional registration
- Maintains full type safety and RPC support through recursive type merging
- Enables clean modular organization of routes

- ✅ Reduced boilerplate code
- ✅ Better type inference and IDE autocomplete
- ✅ Easier code organization and maintainability
- ✅ Declarative conditional routes
- ✅ Full backward compatibility

See the updated README for usage examples.

- All existing tests pass (102/102)
- Added tests for new functionality
- Verified type inference works correctly

- Updated package README with usage examples
76 changes: 76 additions & 0 deletions packages/zod-openapi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,82 @@ const appRoutes = app.openapi(route, (c) => {
const client = hc<typeof appRoutes>('http://localhost:8787/')
```

### Batch Route Registration

For better code organization and type safety, you can use `defineOpenAPIRoute` and `openapiRoutes` to register multiple routes at once.

#### Using `defineOpenAPIRoute`

`defineOpenAPIRoute` provides explicit type safety for route definitions:

```ts
import { OpenAPIHono, defineOpenAPIRoute, createRoute, z } from '@hono/zod-openapi'

const getUserRoute = defineOpenAPIRoute({
route: createRoute({
method: 'get',
path: '/users/{id}',
request: {
params: z.object({ id: z.string() }),
},
responses: {
200: {
content: {
'application/json': {
schema: z.object({ id: z.string(), name: z.string() }),
},
},
},
},
}),
handler: (c) => {
const { id } = c.req.valid('param')
return c.json({ id, name: 'John Doe' }, 200)
},
})
```

#### Using openapiRoutes for Batch Registration

Register multiple routes at once with full type safety:

const app = new OpenAPIHono()

```ts
app.openapiRoutes([getUserRoute, createUserRoute, updateUserRoute] as const) // 'as const' is important for type inference
```

#### Conditional Routes

Use the addRoute flag to conditionally include routes:

```ts
const debugRoute = defineOpenAPIRoute({
route: createRoute({
/* ... */
}),
handler: (c) => {
/* ... */
},
addRoute: process.env.NODE_ENV === 'development', // Only in dev
})
```

#### Modular Organization

Organize routes across multiple files:

```ts
// routes/users.ts
export const userRoutes = [getUserRoute, createUserRoute, updateUserRoute] as const

// app.ts
import { userRoutes } from './routes/users'
import { postRoutes } from './routes/posts'

app.openapiRoutes([...userRoutes, ...postRoutes] as const)
```

## Tips

### Type utilities
Expand Down
12 changes: 0 additions & 12 deletions packages/zod-openapi/eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,7 @@
}
},
"src/index.test.ts": {
"@typescript-eslint/no-deprecated": {
"count": 3
},
"@typescript-eslint/no-unsafe-argument": {
"count": 1
},
"@typescript-eslint/no-unsafe-assignment": {
"count": 5
},
"@typescript-eslint/no-unsafe-member-access": {
"count": 2
},
"@typescript-eslint/require-await": {
"count": 3
}
},
Expand Down
Loading