diff --git a/README.md b/README.md index 87db7e30..ceac4597 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ Instead of adding helpers to `req` and `res`, h3 exposes them as composable util - `setCookie(res, name, value, opts?)` - `deleteCookie(res, name, opts?)` - `useQuery(req)` +- `getRouterParams(event)` - `send(res, data, type?)` - `sendRedirect(res, location, code=302)` - `getRequestHeaders(event, headers)` (alias: `getHeaders`) diff --git a/src/utils/request.ts b/src/utils/request.ts index 71b76956..1667c9e2 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -10,6 +10,17 @@ export function getQuery (event: CompatibilityEvent) { /** @deprecated Use `h3.getQuery` */ export const useQuery = getQuery +export function getRouterParams (event: CompatibilityEvent): CompatibilityEvent['context'] { + // Fallback object needs to be returned in case router is not used (#149) + return event.context.params || {} +} + +export function getRouterParam (event: CompatibilityEvent, name: string): CompatibilityEvent['context'][string] { + const params = getRouterParams(event) + + return params[name] +} + export function getMethod (event: CompatibilityEvent, defaultMethod: HTTPMethod = 'GET'): HTTPMethod { return (event.req.method || defaultMethod).toUpperCase() as HTTPMethod } diff --git a/test/router.test.ts b/test/router.test.ts index bbdcea49..2ba07e93 100644 --- a/test/router.test.ts +++ b/test/router.test.ts @@ -1,6 +1,6 @@ import supertest, { SuperTest, Test } from 'supertest' import { describe, it, expect, beforeEach } from 'vitest' -import { createApp, createRouter, App, Router } from '../src' +import { createApp, createRouter, App, Router, getRouterParams, getRouterParam } from '../src' describe('router', () => { let app: App @@ -61,3 +61,73 @@ describe('router', () => { expect(res.status).toEqual(405) }) }) + +describe('getRouterParams', () => { + let app: App + let request: SuperTest + + beforeEach(() => { + app = createApp({ debug: false }) + request = supertest(app) + }) + + describe('with router', () => { + it('can return router params', async () => { + const router = createRouter().get('/test/params/:name', (request) => { + expect(getRouterParams(request)).toMatchObject({ name: 'string' }) + return '200' + }) + app.use(router) + const result = await request.get('/test/params/string') + + expect(result.text).toBe('200') + }) + }) + + describe('without router', () => { + it('can return an empty object if router is not used', async () => { + app.use('/', (request) => { + expect(getRouterParams(request)).toMatchObject({}) + return '200' + }) + const result = await request.get('/test/empty/params') + + expect(result.text).toBe('200') + }) + }) +}) + +describe('getRouterParam', () => { + let app: App + let request: SuperTest + + beforeEach(() => { + app = createApp({ debug: false }) + request = supertest(app) + }) + + describe('with router', () => { + it('can return a value of router params corresponding to the given name', async () => { + const router = createRouter().get('/test/params/:name', (request) => { + expect(getRouterParam(request, 'name')).toEqual('string') + return '200' + }) + app.use(router) + const result = await request.get('/test/params/string') + + expect(result.text).toBe('200') + }) + }) + + describe('without router', () => { + it('can return `undefined` for any keys', async () => { + app.use('/', (request) => { + expect(getRouterParam(request, 'name')).toEqual(undefined) + return '200' + }) + const result = await request.get('/test/empty/params') + + expect(result.text).toBe('200') + }) + }) +})