Skip to content
Open
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
25 changes: 25 additions & 0 deletions src/helper/route/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Context } from '../../context'
import { Hono } from '../../hono'
import { matchedRoutes, routePath, baseRoutePath, basePath } from '.'

const defaultContextOptions = {
Expand Down Expand Up @@ -217,3 +218,27 @@ describe('basePath', () => {
expect(basePath(c)).toBe('/sub-app-path/foo')
})
})

describe('basePath with Hono instance', () => {
it('should return "/" for a fresh Hono instance', () => {
const app = new Hono()
expect(basePath(app)).toBe('/')
})

it('should return the base path after basePath()', () => {
const app = new Hono().basePath('/api')
expect(basePath(app)).toBe('/api')
})

it('should return the merged path after chained basePath() calls', () => {
const app = new Hono().basePath('/api').basePath('/v1')
expect(basePath(app)).toBe('/api/v1')
})

it('should not affect the original instance', () => {
const app = new Hono()
const based = app.basePath('/api')
expect(basePath(app)).toBe('/')
expect(basePath(based)).toBe('/api')
})
})
25 changes: 22 additions & 3 deletions src/helper/route/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Context } from '../../context'
import { Context } from '../../context'
import type { HonoBase } from '../../hono-base'
import { GET_MATCH_RESULT } from '../../request/constants'
import type { RouterRoute } from '../../types'
import { getPattern, splitRoutingPath } from '../../utils/url'
Expand Down Expand Up @@ -83,7 +84,7 @@ export const baseRoutePath = (c: Context, index?: number): string =>
matchedRoutes(c).at(index ?? c.req.routeIndex)?.basePath ?? ''

/**
* Get the basePath with embedded parameters
* Get the basePath with embedded parameters, or the base path of a Hono instance.
*
* @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.
Expand All @@ -102,9 +103,27 @@ export const baseRoutePath = (c: Context, index?: number): string =>
*
* app.route('/:sub', subApp)
* ```
*
* @example
* ```ts
* import { basePath } from 'hono/route'
*
* const subApp = new Hono()
* const path = basePath(subApp) // '/'
*
* const api = new Hono().basePath('/api')
* const apiPath = basePath(api) // '/api'
* ```
*/
const basePathCacheMap: WeakMap<Context, Record<number, string>> = new WeakMap()
export const basePath = (c: Context, index?: number): string => {
export function basePath(app: HonoBase): string
export function basePath(c: Context, index?: number): string
export function basePath(c: Context | HonoBase, index?: number): string {
if (!(c instanceof Context)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (c as any)._basePath as string
}

index ??= c.req.routeIndex

const cache = basePathCacheMap.get(c) || []
Expand Down