Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/helper/route/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ describe('routePath', () => {

expect(routePath(c)).toBe('/:id')

expect(routePath(c, 0)).toBe('/:id')
expect(routePath(c, 1)).toBe('/:id/:name')
expect(routePath(c, -1)).toBe('/:id/:name')
expect(routePath(c, 2)).toBe('')

c.req.routeIndex = 1
expect(routePath(c)).toBe('/:id/:name')
})
Expand Down Expand Up @@ -96,6 +101,12 @@ describe('baseRoutePath', () => {

expect(baseRoutePath(c)).toBe('/')

expect(baseRoutePath(c, 0)).toBe('/')
expect(baseRoutePath(c, 1)).toBe('/sub')
expect(baseRoutePath(c, 2)).toBe('/:sub')
expect(baseRoutePath(c, -1)).toBe('/:sub')
expect(baseRoutePath(c, 3)).toBe('')

c.req.routeIndex = 1
expect(baseRoutePath(c)).toBe('/sub')

Expand Down Expand Up @@ -129,6 +140,11 @@ describe('basePath', () => {
expect(basePath(c)).toBe('/')
expect(basePath(c)).toBe('/') // cached value

expect(basePath(c, 0)).toBe('/')
expect(basePath(c, 1)).toBe('/sub')
expect(basePath(c, -1)).toBe('/sub')
expect(basePath(c, 2)).toBe('')

c.req.routeIndex = 1
expect(basePath(c)).toBe('/sub')
})
Expand Down
29 changes: 20 additions & 9 deletions src/helper/route/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,32 @@ export const matchedRoutes = (c: Context): RouterRoute[] =>
* Get the route path registered within the handler
*
* @param {Context} c - The context object
* @param {number} index - The index of the root from which to retrieve the path, similar to Array.prototype.at(), where a negative number is the index counted from the end of the matching root. Defaults to the current root index.
* @returns The route path registered within the handler
*
* @example
* ```ts
* import { routePath } from 'hono/route'
*
* app.use('*', (c, next) => {
* console.log(routePath(c)) // '*'
* console.log(routePath(c, -1)) // '/posts/:id'
* return next()
* })
*
* app.get('/posts/:id', (c) => {
* return c.text(routePath(c)) // '/posts/:id'
* })
* ```
*/
export const routePath = (c: Context): string => matchedRoutes(c)[c.req.routeIndex].path
export const routePath = (c: Context, index?: number): string =>
matchedRoutes(c).at(index ?? c.req.routeIndex)?.path ?? ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't easy to define the behavior if it cannot find the route. I think both '' and undefined are okay. In this case, '' is better because this way does not break that routePath returns value is string (not string | undefined). So this is good.


/**
* Get the basePath of the as-is route specified by routing.
*
* @param {Context} c - The context object
* @param {number} index - The index of the root from which to retrieve the path, similar to Array.prototype.at(), where a negative number is the index counted from the end of the matching root. Defaults to the current root index.
* @returns The basePath of the as-is route specified by routing.
*
* @example
Expand All @@ -70,12 +79,14 @@ export const routePath = (c: Context): string => matchedRoutes(c)[c.req.routeInd
* app.route('/:sub', subApp)
* ```
*/
export const baseRoutePath = (c: Context): string => matchedRoutes(c)[c.req.routeIndex].basePath
export const baseRoutePath = (c: Context, index?: number): string =>
matchedRoutes(c).at(index ?? c.req.routeIndex)?.basePath ?? ''

/**
* Get the basePath with embedded parameters
*
* @param {Context} c - The context object
* @param {number} index - The index of the root from which to retrieve the path, similar to Array.prototype.at(), where a negative number is the index counted from the end of the matching root. Defaults to the current root index.
* @returns The basePath with embedded parameters.
*
* @example
Expand All @@ -92,17 +103,17 @@ export const baseRoutePath = (c: Context): string => matchedRoutes(c)[c.req.rout
* app.route('/:sub', subApp)
* ```
*/
const basePathCacheMap: WeakMap<Context, string[]> = new WeakMap()
export const basePath = (c: Context): string => {
const routeIndex = c.req.routeIndex
const basePathCacheMap: WeakMap<Context, Record<number, string>> = new WeakMap()
export const basePath = (c: Context, index?: number): string => {
index ??= c.req.routeIndex

const cache = basePathCacheMap.get(c) || []
if (typeof cache[routeIndex] === 'string') {
return cache[routeIndex]
if (typeof cache[index] === 'string') {
return cache[index]
}

let result: string
const rp = baseRoutePath(c)
const rp = baseRoutePath(c, index)
if (!/[:*]/.test(rp)) {
result = rp
} else {
Expand All @@ -123,7 +134,7 @@ export const basePath = (c: Context): string => {
result = reqPath.substring(0, basePathLength)
}

cache[routeIndex] = result
cache[index] = result
basePathCacheMap.set(c, cache)

return result
Expand Down
Loading