Skip to content

Instantly share code, notes, and snippets.

@yusukebe
Created December 8, 2023 01:08
Show Gist options
  • Save yusukebe/ec25489ac89008a5b96052ebc6699fe9 to your computer and use it in GitHub Desktop.
Save yusukebe/ec25489ac89008a5b96052ebc6699fe9 to your computer and use it in GitHub Desktop.
import { Hono } from 'hono'
import type { H, MiddlewareHandler } from 'hono/types'
const METHODS = ['GET', 'POST', 'PUT', 'DELETE'] as const
type RouteFile = {
default?: Hono | Function
} & { [M in (typeof METHODS)[number]]?: H[] }
type RendererFile = {
default: MiddlewareHandler
}
const filePathToPath = (filePath: string) => {
filePath = filePath
.replace(/\.tsx?$/g, '')
.replace(/^\/?index/, '/') // `/index`
.replace(/\/index/, '') // `/about/index`
.replace(/\[\.{3}.+\]/, '*')
.replace(/\[(.+)\]/, ':$1')
return /^\//.test(filePath) ? filePath : '/' + filePath
}
const pathTodDirPath = (path: string) => {
const dirPath = path.replace(/[^\/]+$/, '')
return dirPath
}
export const createApp = () => {
const RENDERERS = import.meta.glob<RendererFile>('/app/routes/**/_renderer.tsx', {
eager: true
})
const ROUTES = import.meta.glob<RouteFile>('/app/routes/**/[a-z0-9[-][a-z0-9[_-]*.(ts|tsx)', {
eager: true
})
const app = new Hono()
for (const [key, routes] of Object.entries(RENDERERS)) {
const dirPath = pathTodDirPath(key)
const renderer = routes.default
const path = dirPath.replace(/^\/app\/routes/, '')
app.get(`${path}*`, renderer)
}
for (const [key, route] of Object.entries(ROUTES)) {
const path = filePathToPath(key.replace(/^\/app\/routes/, ''))
for (const m of METHODS) {
const handlers = route[m]
if (handlers) {
app.on(m, path, ...handlers)
}
}
if (route.default) {
if (route.default instanceof Hono) {
app.route(path, route.default)
} else if (typeof route.default === 'function') {
app.get(path, (c) => {
return c.render((route.default as Function)(c))
})
}
}
}
return app
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment