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() => unknown—Custom handler for unmatched routes
loggerTConsoleBase—Custom logger instance
routerobject—Router options (ignoreTrailingSlash, ignoreCase, cacheLimit)
requestLimitsobject—Default request body size limits
defaultHeadersRecord<string, string>—Headers added to every response
responseClasstypeof WooksHttpResponse—Custom 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.