Skip to content

@hoajs/adapter

This package provides an adapter that lets a Hoa application run seamlessly on a Node.js HTTP server. Under the hood it uses createServerAdapter from @whatwg-node/server to bridge WHATWG Fetch–style Request/Response with Node's http.Server.

Quick Start

ts
import { Hoa } from 'hoa'
import { nodeServer } from '@hoajs/adapter'

const app = new Hoa()
app.extend(nodeServer())

app.use(async (ctx) => {
  ctx.res.body = 'Hello, Hoa!'
})

app.listen(3000, () => {
  console.log('Listening on 3000')
})

app.listen

Hoa's app.listen delegates to Node's server.listen(...) and supports the same call signatures. See the official Node.js docs: server.listen()

js
app.listen(handle[, backlog][, callback])
app.listen(options[, callback])
app.listen(path[, backlog][, callback])
app.listen([port[, host[, backlog]]][, callback])

app.callback

app.callback() returns a Node.js request listener (req, res) => void backed by the same WHATWG Fetch adapter that powers app.listen. Use it when you want to mount Hoa inside an existing http.Server, integrate with testing libraries such as supertest, or wrap the listener with custom server logic.

js
import { createServer } from 'http'
import { Hoa } from 'hoa'
import { nodeServer } from '@hoajs/adapter'

const app = new Hoa()
app.extend(nodeServer())

app.use(async (ctx) => {
  ctx.res.body = 'Hello, Hoa!'
})

const server = createServer(app.callback())
server.listen(3000)

Testing with supertest

app.callback() is the recommended entry point for HTTP-level testing without binding to a real port:

js
import request from 'supertest'
import { Hoa } from 'hoa'
import { nodeServer } from '@hoajs/adapter'

const app = new Hoa()
app.extend(nodeServer())
app.use(async (ctx) => {
  ctx.res.body = 'Hello, Hoa!'
})

await request(app.callback())
  .get('/')
  .expect(200, 'Hello, Hoa!')

Note: app.callback() and app.listen() share the same underlying adapter, so behavior is identical. The only difference is that app.callback() does not start a server — you are responsible for binding it with http.createServer, https.createServer, or a test harness.

Node.js interoperability

Hoa works with web-standard body types (e.g. string, Blob, ArrayBuffer, TypedArray, ReadableStream). When returning Node.js primitives, you may need to convert them into their web equivalents:

  • Buffer → ArrayBuffer (Optional)
  • Node.js Readable stream → Web ReadableStream

Example: Buffer to ArrayBuffer

js
app.use(async (ctx) => {
  const buf = Buffer.from('Hello, Hoa!')
  // Convert Buffer to ArrayBuffer
  const arrayBuffer = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
  ctx.res.body = arrayBuffer
  // ctx.res.body = buf // buf is a Uint8Array instance and also works directly
})

Example: Node.js stream to Web ReadableStream

js
import { Readable } from 'node:stream'

app.use(async (ctx) => {
  const nodeStream = Readable.from(['Hello, ', 'Hoa!'])
  // Convert Node.js Readable stream to Web ReadableStream
  const webStream = Readable.toWeb(nodeStream)
  ctx.res.body = webStream
})