Skip to content

H3 Integration

Use Wooks composables with H3 — register Wooks-style route handlers on top of an existing H3 app. Unmatched requests automatically fall through to H3 handlers.

INFO

Source code and issues: github.com/wooksjs/h3-adapter

Install

bash
npm install @wooksjs/h3-adapter @wooksjs/event-http wooks h3

Quick Start

ts
import { H3, toNodeHandler } from 'h3/node'
import { WooksH3 } from '@wooksjs/h3-adapter'
import { useRouteParams } from '@wooksjs/event-http'
import { createServer } from 'http'

const app = new H3()
const wooks = new WooksH3(app)

wooks.get('/hello/:name', () => {
    const { get } = useRouteParams()
    return { hello: get('name') }
})

const handler = toNodeHandler(app)
createServer(handler).listen(3000, () => {
    console.log('Server running on http://localhost:3000')
})

How It Works

When a request comes in:

  1. Wooks checks if a matching route is registered
  2. If matched — the Wooks handler runs with full composable support
  3. If not matched — the request falls through to H3 handlers

This means you can mix Wooks routes with H3 routes side by side:

ts
const app = new H3()
const wooks = new WooksH3(app)

// Wooks route — uses composables
wooks.get('/wooks-route', () => {
    const { get } = useRouteParams()
    return 'handled by wooks'
})

// H3 route — uses h3 event API
app.on('GET', '/h3-route', (event) => {
    return 'handled by h3'
})

Node runtime required

WooksH3 reads the raw Node req/res from event.node, so serve the app via toNodeHandler() / serve() from h3/node (as in the Quick Start). On edge/worker runtimes Wooks routes are skipped and requests fall through to H3.

API

new WooksH3(h3App, options?)

Creates a new adapter instance on top of an H3 app.

OptionTypeDefaultDescription
raise404booleanfalseReturn 404 for unmatched routes instead of falling through to H3
onNotFound() => unknownCustom handler for unmatched routes
loggerTConsoleBaseCustom logger instance
routerobjectRouter options (ignoreTrailingSlash, ignoreCase, cacheLimit)
requestLimitsobjectDefault request body size limits
defaultHeadersRecord<string, string>Headers added to every response
responseClasstypeof WooksHttpResponseCustom response class, see Error Responses

Route Methods

ts
wooks.get(path, handler)
wooks.post(path, handler)
wooks.put(path, handler)
wooks.patch(path, handler)
wooks.delete(path, handler)
wooks.head(path, handler)
wooks.options(path, handler)
wooks.all(path, handler)

Handlers take no arguments — use composables to access request data:

ts
wooks.get('/users/:id', () => {
    const { get } = useRouteParams()
    return { userId: get('id') }
})

Usage Examples

Reading Request Body

ts
wooks.post('/data', async () => {
    const { rawBody } = useRequest()
    const body = await rawBody()
    return { received: body.toString() }
})

Setting Response Headers

ts
wooks.get('/custom-headers', () => {
    const response = useResponse()
    response.setHeader('x-powered-by', 'wooks')
    response.setStatus(200)
    return { ok: true }
})

Error Handling

ts
wooks.get('/protected', () => {
    throw new HttpError(403, 'Forbidden')
})

Options Example

ts
const wooks = new WooksH3(app, {
    raise404: true,

    onNotFound: () => {
        const response = useResponse()
        response.setStatus(404)
        return { error: 'not found' }
    },

    defaultHeaders: {
        'x-powered-by': 'wooks',
    },

    requestLimits: {
        maxCompressed: 1_048_576,
        maxInflated: 10_485_760,
    },
})

Available Composables

All @wooksjs/event-http composables work inside Wooks handlers — see the Composables reference.

Released under the MIT License.