Skip to Content

Hono

Hono is fetch-native, so the same handler runs on Node, Workers, Deno and Bun. Only the upgradeWebSocket helper differs per runtime, and you pass it in — which is the whole reason this adapter is the thinnest of the set.

Install

npm install @luno-oss/core @luno-oss/hono hono

Plus the server and WebSocket helpers for your runtime — on Node, @hono/node-server and @hono/node-ws.

Mount it

import { serve } from '@hono/node-server' import { createNodeWebSocket } from '@hono/node-ws' import { Hono } from 'hono' import { createLuno, memoryStore } from '@luno-oss/core' import { registerLuno } from '@luno-oss/hono' const luno = createLuno({ store: memoryStore(), secret: process.env.LUNO_SECRET! }) const app = new Hono() const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app }) registerLuno(app, { luno, upgradeWebSocket }) const server = serve({ fetch: app.fetch, port: 3000 }) injectWebSocket(server)

API

ExportPurpose
lunoHono(options)Returns a standalone Hono app carrying all three routes
registerLuno(app, options, basePath?)Mounts that app onto one you already have
interface LunoHonoOptions { luno: Luno upgradeWebSocket: UpgradeWebSocket paths?: { enroll?: string; enrollStatus?: string; ws?: string } }

Paths default to /enroll, /enroll/status and /ws. Mount under a prefix with registerLuno(app, options, '/api/luno') — just make sure the URL you give the node at pairing time matches.

Serving it standalone

import { lunoHono } from '@luno-oss/hono' const app = lunoHono({ luno, upgradeWebSocket })

Use this when Luno is the whole service. Use registerLuno when it is one part of a larger app.

The REST routes hand c.req.raw — a real Request — straight to luno.http.handle, with no shim at all. That is the payoff of the core accepting a structural { method, url, json() }.

Next