Describe the feature
With 1.8.0 can now have better typing for query parameters and body content using eventHandler generic.
We also have a proper way to define per event middlewares stack using onRequest
The issue is that it's difficult to type event context.
We can use typescript interface augmentation, but this impact all events in the project:
declare module 'h3' {
interface H3EventContext {
auth: { name: string }
}
}
export default defineEventHandler(async (event) => {
event.context.auth.name // string
}
Before 1.8.0, we could create a custom eventHandler wrapper and use an extended version of H3Event:
import type { H3Event, H3EventContext } from 'h3'
// custom event
interface H3CustomEvent extends H3Event {
context: H3EventContext & {
auth: { name: string }
}
}
// custom event handler
function defineCustomEventHandler<T>(handler: (event: H3CustomEvent) => T) {
return defineEventHandler(async (event) => {
event.context.auth = { name: 'username' }
eturn handler(event as H3CustomEvent)
}
})
// usage
export default defineCustomEventHandler(async (event) => {
event.context.auth.name // string
}
Same wrapper with `1.8.0`
// EventHandlerRequest, EventHandlerResponse, EventHandler are not exported
interface EventHandlerRequest {
body?: any
query?: QueryObject
}
type EventHandlerResponse<T = any> = T | Promise<T>
interface EventHandler<
Request extends EventHandlerRequest = EventHandlerRequest,
Response extends EventHandlerResponse = EventHandlerResponse,
> {
__is_handler__?: true
(event: H3Event<Request>): Response
}
// custom event
interface H3CustomEvent<T extends EventHandlerRequest = EventHandlerRequest>
extends H3Event<T> {
context: H3EventContext & {
auth: { name: string }
}
}
// custom event handler
export function customEventHandler<
Request extends EventHandlerRequest = EventHandlerRequest,
Response extends EventHandlerResponse = EventHandlerResponse,
>(
handler: EventHandler<
Request extends EventHandlerRequest ? Request : EventHandlerRequest,
Request extends EventHandlerRequest ? Response : Request
>,
): EventHandler<
Request extends EventHandlerRequest ? Request : EventHandlerRequest,
Request extends EventHandlerRequest ? Response : Request
> {
//
return eventHandler((event) => {
event.context.auth = { name: 'username' }
return handler(event as H3CustomEvent<Request>)
})
}
// usage
export default customEventHandler((event) => {
event.context.auth.name // string
})
Since usage of generics (and methods overloading), it's harder to wrap.
How about extending context with EventHandlerRequest, same as query and body like:
const auth = defineRequestMiddleware<{
context: {
auth: {
name: string
}
}
}>((event) => {
event.context.auth.name // string
})
export default eventHandler<{
context: {
auth: {
name: string
}
}
}>({
onRequest: [auth],
async handler(event) {
event.context.auth.name // string
},
})
Additional information
Describe the feature
With 1.8.0 can now have better typing for query parameters and body content using
eventHandlergeneric.We also have a proper way to define per event middlewares stack using
onRequestThe issue is that it's difficult to type event context.
We can use typescript interface augmentation, but this impact all events in the project:
Before
1.8.0, we could create a customeventHandlerwrapper and use an extended version ofH3Event:Same wrapper with `1.8.0`
Since usage of generics (and methods overloading), it's harder to wrap.
How about extending context with
EventHandlerRequest, same asqueryandbodylike:Additional information