Hono
Before
ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import { PostService } from '@packages/service'
import { PostDomain } from '@packages/domain'
import { postSchema } from '@packages/schemas'
import { Post } from '@packages/prisma'
export class PostHandler {
static apply(app: Hono) {
return app
.post(
'/posts',
zValidator(
'json',
postSchema.pick({
post: true,
}),
),
async (c) => {
try {
const valid = c.req.valid('json')
const req = valid.post
await PostService.createPost(req)
return c.json({ message: 'Created' }, 201)
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
},
)
.get(
'/posts',
zValidator(
'query',
z.object({
page: z.string(),
rows: z.string(),
}),
),
async (c) => {
try {
const valid = c.req.valid('query')
const { page, rows } = PostDomain.convertNumberQueryParams(valid)
if (isNaN(page) || isNaN(rows) || page < 1 || rows < 1) {
return c.json({ message: 'Bad Request' }, 400)
}
const limit = rows
const offset = (page - 1) * rows
const res: Post[] = await PostService.getPosts(limit, offset)
return c.json(res, 200)
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
},
)
.put(
'/posts/:id',
zValidator('param', z.object({ id: z.string().uuid() })),
zValidator('json', postSchema.pick({ post: true })),
async (c) => {
try {
const param_valid = c.req.valid('param')
const id = param_valid.id
const json_valid = c.req.valid('json')
const { post } = json_valid
await PostService.putPost(id, post)
return new Response(null, { status: 204 })
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
},
)
.delete(
'/posts/:id',
zValidator(
'param',
z.object({
id: z.string().uuid(),
}),
),
async (c) => {
try {
const valid = c.req.valid('param')
const id = valid.id
await PostService.deletePost(id)
return new Response(null, { status: 204 })
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
},
)
}
}
Middleware
ts
import * as dotenv from 'dotenv'
import { logger } from 'hono/logger'
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import { HonoHandler } from '../handler/hono_handler'
import { PostHandler } from '../handler/post_handler'
dotenv.config()
export class App {
static init() {
const app = new Hono()
const defaultPort = 3001
const port = process.env.PORT !== undefined ? parseInt(process.env.PORT) : defaultPort
console.log(`Server is running on http://localhost:${port}`)
app.use('*', logger())
app.use('*', async (c, next) => {
console.log(` ::: ${c.req.method} ${c.req.url}`)
return next()
})
app.use('*', async (c, next) => {
try {
await next()
} catch (e) {
return c.json({ error: (e as Error).message }, 500)
}
})
serve({
fetch: app.fetch,
port,
})
return this.applyRoutes(app)
}
static applyRoutes(app: Hono) {
return app.route('/', HonoHandler.apply(app)).route('/', PostHandler.apply(app))
}
}
After
ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import { PostService } from '@packages/service'
import { PostDomain } from '@packages/domain'
import { postSchema } from '@packages/schemas'
import { Post } from '@packages/prisma'
export class PostHandler {
static apply(app: Hono) {
return app
.post(
'/posts',
zValidator(
'json',
postSchema.pick({
post: true,
}),
),
async (c) => {
const valid = c.req.valid('json')
const req = valid.post
await PostService.createPost(req)
return c.json({ message: 'Created' }, 201)
},
)
.get(
'/posts',
zValidator(
'query',
z.object({
page: z.string(),
rows: z.string(),
}),
),
async (c) => {
const valid = c.req.valid('query')
const { page, rows } = PostDomain.convertNumberQueryParams(valid)
if (isNaN(page) || isNaN(rows) || page < 1 || rows < 1) {
return c.json({ message: 'Bad Request' }, 400)
}
const limit = rows
const offset = (page - 1) * rows
const res: Post[] = await PostService.getPosts(limit, offset)
return c.json(res, 200)
},
)
.put(
'/posts/:id',
zValidator('param', z.object({ id: z.string().uuid() })),
zValidator('json', postSchema.pick({ post: true })),
async (c) => {
const param_valid = c.req.valid('param')
const id = param_valid.id
const json_valid = c.req.valid('json')
const { post } = json_valid
await PostService.putPost(id, post)
return new Response(null, { status: 204 })
},
)
.delete(
'/posts/:id',
zValidator(
'param',
z.object({
id: z.string().uuid(),
}),
),
async (c) => {
const valid = c.req.valid('param')
const id = valid.id
await PostService.deletePost(id)
return new Response(null, { status: 204 })
},
)
}
}
OpenAPIHono
Before
ts
import { OpenAPIHono } from '@hono/zod-openapi'
import { Post } from '@packages/prisma'
import { PostDomain } from '@packages/domain'
import { PostService } from '@packages/service'
import { postRoutes } from '../openapi'
export class PostHandler {
static apply(app: OpenAPIHono) {
return app
.openapi(postRoutes['createPost'], async (c) => {
try {
const valid = c.req.valid('json')
const req = valid.post
await PostService.createPost(req)
return c.json({ message: 'Created' }, 201)
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
})
.openapi(postRoutes['getPostList'], async (c) => {
try {
const valid = c.req.valid('query')
const { page, rows } = PostDomain.convertNumberQueryParams(valid)
if (isNaN(page) || isNaN(rows) || page < 1 || rows < 1) {
return c.json({ message: 'Bad Request' }, 400)
}
const limit = rows
const offset = (page - 1) * rows
const res: Post[] = await PostService.getPosts(limit, offset)
return c.json(res, 200)
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
})
.openapi(postRoutes['updatePost'], async (c) => {
try {
const param_valid = c.req.valid('param')
const id = param_valid.id
const json_valid = c.req.valid('json')
const { post } = json_valid
await PostService.putPost(id, post)
return new Response(null, { status: 204 })
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
})
.openapi(postRoutes['deletePost'], async (c) => {
try {
const valid = c.req.valid('param')
const id = valid.id
await PostService.deletePost(id)
return new Response(null, { status: 204 })
} catch (e) {
console.log(e)
return c.json({ message: 'Internal Server Error' }, 500)
}
})
}
}
Middleware
ts
import * as dotenv from 'dotenv'
import { OpenAPIHono } from '@hono/zod-openapi'
import { logger } from 'hono/logger'
import { OpenAPIHonoHandler } from '../handler/openapi_hono_handler'
import { PostHandler } from '../handler/post_handler'
import { SwaggerHandler } from '../handler/swagger_handler'
import { serve } from '@hono/node-server'
dotenv.config()
export class App {
static init() {
const app = new OpenAPIHono()
app.use('*', logger())
app.use('*', (c, next) => {
console.log(` ::: ${c.req.method} ${c.req.url}`)
return next()
})
const defaultPort = 3002
const port = process.env.PORT !== undefined ? parseInt(process.env.PORT) : defaultPort
console.log(`Server is running on http://localhost:${port}`)
serve({
fetch: app.fetch,
port,
})
app.use('*', async (c, next) => {
try {
await next()
} catch (e) {
return c.json({ error: (e as Error).message }, 500)
}
})
return this.applyRoutes(app)
}
static applyRoutes(app: OpenAPIHono) {
return app
.route('/', OpenAPIHonoHandler.apply(app))
.route('/', PostHandler.apply(app))
.route('/', SwaggerHandler.apply(app))
}
}
After
ts
import { OpenAPIHono } from '@hono/zod-openapi'
import { Post } from '@packages/prisma'
import { PostDomain } from '@packages/domain'
import { PostService } from '@packages/service'
import { postRoutes } from '../openapi'
export class PostHandler {
static apply(app: OpenAPIHono) {
return app
.openapi(postRoutes['createPost'], async (c) => {
const valid = c.req.valid('json')
const req = valid.post
await PostService.createPost(req)
return c.json({ message: 'Created' }, 201)
})
.openapi(postRoutes['getPostList'], async (c) => {
const valid = c.req.valid('query')
const { page, rows } = PostDomain.convertNumberQueryParams(valid)
if (isNaN(page) || isNaN(rows) || page < 1 || rows < 1) {
return c.json({ message: 'Bad Request' }, 400)
}
const limit = rows
const offset = (page - 1) * rows
const res: Post[] = await PostService.getPosts(limit, offset)
return c.json(res, 200)
})
.openapi(postRoutes['updatePost'], async (c) => {
const param_valid = c.req.valid('param')
const id = param_valid.id
const json_valid = c.req.valid('json')
const { post } = json_valid
await PostService.putPost(id, post)
return new Response(null, { status: 204 })
})
.openapi(postRoutes['deletePost'], async (c) => {
const valid = c.req.valid('param')
const id = valid.id
await PostService.deletePost(id)
return new Response(null, { status: 204 })
})
}
}