feat(app): integrate Hono framework for improved routing and error handling

- Replaced the previous application instance with Hono for better routing capabilities.
- Updated OpenAPI route registration to use a new internal path structure.
- Enhanced error handling by utilizing Hono's built-in error management features.
- Adjusted logging to reflect the new route paths for OpenAPI documentation.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2025-11-14 23:37:16 +08:00
parent 3f27b971f6
commit 0621909e49
3 changed files with 17 additions and 15 deletions

View File

@@ -4,6 +4,7 @@ import { env } from '@afilmory/env'
import type { HonoHttpApplication } from '@afilmory/framework'
import { createApplication, createLogger, createZodValidationPipe, HttpException } from '@afilmory/framework'
import { BizException } from 'core/errors'
import { Hono } from 'hono'
import { PgPoolProvider } from './database/database.provider'
import { AllExceptionsFilter } from './filters/all-exceptions.filter'
@@ -31,10 +32,15 @@ const GlobalValidationPipe = createZodValidationPipe({
const honoErrorLogger = createLogger('HonoErrorHandler')
export async function createConfiguredApp(options: BootstrapOptions = {}): Promise<HonoHttpApplication> {
const app = await createApplication(AppModules, {
globalPrefix: options.globalPrefix ?? '/api',
})
const hono = new Hono()
registerOpenApiRoutes(hono, { globalPrefix: options.globalPrefix ?? '/api' })
const app = await createApplication(
AppModules,
{
globalPrefix: options.globalPrefix ?? '/api',
},
hono,
)
const container = app.getContainer()
app.useGlobalFilters(new AllExceptionsFilter())
@@ -51,9 +57,6 @@ export async function createConfiguredApp(options: BootstrapOptions = {}): Promi
const redisProvider = container.resolve(RedisProvider)
await redisProvider.warmup()
registerOpenApiRoutes(app.getInstance(), { globalPrefix: options.globalPrefix ?? '/api' })
const hono = app.getInstance()
hono.onError((error, context) => {
if (error instanceof BizException) {
return new Response(JSON.stringify(error.toResponse()), {

View File

@@ -21,8 +21,6 @@ function normalizePrefix(prefix: string): string {
export function registerOpenApiRoutes(app: Hono, options: RegisterOpenApiOptions): void {
const prefix = normalizePrefix(options.globalPrefix)
const specPath = `${prefix}/openapi.json`
const docsPath = `${prefix}/docs`
const document = createOpenApiDocument(AppModules, {
title: 'Core Service API',
@@ -32,14 +30,14 @@ export function registerOpenApiRoutes(app: Hono, options: RegisterOpenApiOptions
servers: prefix ? [{ url: prefix }] : undefined,
})
app.get(specPath || '/openapi.json', (context) => context.json(document))
app.get('/internal/openapi.json', (context) => context.json(document))
app.get(docsPath || '/docs', (context) => {
app.get('/internal/docs', (context) => {
context.header('content-type', 'text/html; charset=utf-8')
return context.html(renderScalarHtml(specPath || '/openapi.json'))
return context.html(renderScalarHtml('/internal/openapi.json'))
})
logger.info(`OpenAPI routes registered: http://localhost:${env.PORT}${docsPath}`)
logger.info(`OpenAPI routes registered: http://localhost:${env.PORT}/internal/docs`)
}
function renderScalarHtml(specUrl: string): string {

View File

@@ -113,7 +113,6 @@ function isOnApplicationShutdownHook(value: unknown): value is OnApplicationShut
}
export class HonoHttpApplication {
private readonly app = new Hono()
private readonly container: DependencyContainer
private readonly globalEnhancers: GlobalEnhancerRegistry = createDefaultRegistry()
private readonly registeredModules = new Set<Constructor>()
@@ -143,6 +142,7 @@ export class HonoHttpApplication {
constructor(
private readonly rootModule: Constructor,
private readonly options: ApplicationOptions = {},
private readonly app: Hono,
) {
this.logger = options.logger ?? createLogger('Framework')
this.diLogger = this.logger.extend('DI')
@@ -1313,8 +1313,9 @@ export class HonoHttpApplication {
export async function createApplication(
rootModule: Constructor,
options: ApplicationOptions = {},
hono: Hono = new Hono(),
): Promise<HonoHttpApplication> {
const app = new HonoHttpApplication(rootModule, options)
const app = new HonoHttpApplication(rootModule, options, hono)
await app.init()
return app
}