Changelog - 2026-01-07
Controller Factory Route Customization
This release enhances the Controller Factory with comprehensive request/response schema customization.
Overview
- Route Customization: New
requestandresponseconfiguration for all CRUD routes - Generic Definitions: Controllers now preserve route definition types for better IDE support
- Compact Descriptions: OpenAPI route descriptions made more concise
- Response Metadata: Added meaningful response descriptions for API explorers
New Features
Enhanced Route Customization
Files:
packages/core/src/base/controllers/factory/definition.tspackages/core/src/base/controllers/common/types.ts
Problem: Users could only customize requestBody and schema (response). No way to customize query parameters, headers, or path parameters.
Solution: New unified request and response configuration objects:
routes: {
create: {
authStrategies: ['jwt'],
request: {
body: CreateUserSchema, // Custom request body
headers: CustomHeadersSchema, // Custom headers
},
response: {
schema: PublicUserSchema, // Custom response body
},
},
find: {
skipAuth: true,
request: {
query: CustomQuerySchema, // Custom query parameters
},
response: {
schema: z.array(PublicUserSchema),
},
},
}Customizable Components per Route:
| Route | query | headers | params | body | response |
|---|---|---|---|---|---|
| COUNT | ✅ | ✅ | - | - | ✅ |
| FIND | ✅ | ✅ | - | - | ✅ |
| FIND_BY_ID | ✅ | ✅ | ✅ | - | ✅ |
| FIND_ONE | ✅ | ✅ | - | - | ✅ |
| CREATE | - | ✅ | - | ✅ | ✅ |
| UPDATE_BY_ID | - | ✅ | ✅ | ✅ | ✅ |
| UPDATE_BY | ✅ | ✅ | - | ✅ | ✅ |
| DELETE_BY_ID | - | ✅ | ✅ | - | ✅ |
| DELETE_BY | ✅ | ✅ | - | - | ✅ |
Generic Controller Definitions
Files:
packages/core/src/base/controllers/abstract.tspackages/core/src/base/controllers/base.tspackages/core/src/base/controllers/factory/controller.ts
Problem: Route definition types were lost, preventing proper type inference in overridden methods.
Solution: Added Definitions generic parameter to AbstractController and BaseController:
export abstract class AbstractController<
RouteEnv extends Env = Env,
RouteSchema extends Schema = {},
BasePath extends string = '/',
ConfigurableOptions extends object = {},
Definitions extends Record<string, TAuthRouteConfig<RouteConfig>> = Record<...>,
>The definitions property now preserves the actual route definition types.
Compact OpenAPI Descriptions
File: packages/core/src/base/controllers/factory/definition.ts
Before:
description: 'Returns the total count of records matching the optional where condition. Useful for pagination metadata or checking data existence without fetching records.'After:
description: 'Count records matching where condition'All route descriptions are now concise and easy to read in API explorers.
Response Metadata
File: packages/core/src/base/controllers/factory/definition.ts
Added meaningful response descriptions for OpenAPI:
| Route | Response Description |
|---|---|
| COUNT | Total count of matching records |
| FIND | Array of matching records (with optional count) |
| FIND_BY_ID | Single record matching ID or null |
| FIND_ONE | First matching record or null |
| CREATE | Created record with generated fields (id, createdAt, etc.) |
| UPDATE_BY_ID | Updated record with all current fields |
| UPDATE_BY | Array of updated records |
| DELETE_BY_ID | Deleted record data |
| DELETE_BY | Array of deleted records |
Files Changed
Core Package (packages/core)
| File | Changes |
|---|---|
src/base/controllers/abstract.ts | Added Definitions generic parameter |
src/base/controllers/base.ts | Added Definitions generic parameter |
src/base/controllers/common/types.ts | Added route config types |
src/base/controllers/factory/controller.ts | Made ICrudControllerOptions generic, added type casts |
src/base/controllers/factory/definition.ts | Updated route configs, compact descriptions, response metadata |
Examples (examples/vert)
| File | Changes |
|---|---|
src/controllers/configuration.controller.ts | Updated to use new route customization syntax |
Migration Guide
Step 1: Update Route Configuration Syntax
Before:
routes: {
create: {
requestBody: CreateSchema,
schema: ResponseSchema,
}
}After:
routes: {
create: {
request: { body: CreateSchema },
response: { schema: ResponseSchema },
}
}Step 2: Method Overrides
When overriding controller methods, use TRouteContext for typed arguments. You can manually type the request body using context.req.valid<T>('json') or infer it from your Zod schema.
import { TRouteContext } from '@venizia/ignis';
import { z } from '@hono/zod-openapi';
// Infer type from your schema
type CreateBody = z.infer<typeof CreateSchema>;
// Override method
override async create(opts: { context: TRouteContext }) {
const { context } = opts;
// Use explicit generic for strict typing
const data = context.req.valid<CreateBody>('json');
// ... custom logic
return super.create(opts);
}