@rudderjs/server-hono 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,89 @@
1
+ # @rudderjs/server-hono
2
+
3
+ ## Overview
4
+
5
+ Hono-based HTTP server adapter — the default server in every RudderJS app. Implements the `ServerAdapterProvider` contract and wires up routing, middleware, CORS, request logging, IP extraction, the Vike SSR fetch handler, and the WebSocket upgrade bridge. You rarely touch this package directly; the `hono()` factory goes into `bootstrap/app.ts` as the `server` field and you forget about it.
6
+
7
+ ## Key Patterns
8
+
9
+ ### Wiring
10
+
11
+ ```ts
12
+ // bootstrap/app.ts
13
+ import { Application } from '@rudderjs/core'
14
+ import { hono } from '@rudderjs/server-hono'
15
+ import configs from '../config/index.js'
16
+ import providers from './providers.js'
17
+
18
+ export default Application.configure({
19
+ server: hono(configs.server),
20
+ config: configs,
21
+ providers,
22
+ }).withRouting({...}).create()
23
+ ```
24
+
25
+ ### Config
26
+
27
+ ```ts
28
+ // config/server.ts
29
+ import { Env } from '@rudderjs/support'
30
+
31
+ export default {
32
+ port: Env.getNumber('PORT', 3000),
33
+ trustProxy: Env.getBool('TRUST_PROXY', false),
34
+ cors: {
35
+ origin: Env.get('CORS_ORIGIN', '*'),
36
+ methods: 'GET,POST,PUT,PATCH,DELETE,OPTIONS',
37
+ headers: 'Content-Type,Authorization',
38
+ },
39
+ }
40
+ ```
41
+
42
+ ### What it does at runtime
43
+
44
+ - Mounts the router's registered routes onto a Hono app
45
+ - Applies global middleware → group middleware (`m.web` / `m.api`) → per-route middleware → handler
46
+ - Runs CORS + request logger
47
+ - Exposes `req.ip` via `extractIp()` (trust-proxy aware)
48
+ - Detects `ViewResponse` from controller handlers and resolves via Vike's `renderPage()`
49
+ - Detects `HttpException` + `ValidationError` and renders them
50
+ - Attaches the `__rudderjs_ws_upgrade__` handler in production (dev goes through `@rudderjs/vite`)
51
+ - Returns a WinterCG-compliant `fetch` function — same code works on Node, Bun, Deno, Cloudflare Workers
52
+
53
+ ### Req/res state on the Hono context
54
+
55
+ Per-request state lives on the Hono `c` context via getters — `req.body`, `req.session`, `req.user`, response body. Because `normalizeRequest(c)` is called twice per request (once for `applyMiddleware`, once for `registerRoute`), **plain property sets don't cross between the two calls**. Mutations to `req` must live on `c` directly (e.g. `c.set('user', user)`), not on the normalized `req` object.
56
+
57
+ ### IP extraction
58
+
59
+ ```ts
60
+ const ip = req.ip // set by server-hono's extractIp()
61
+ ```
62
+
63
+ `req.ip` is the canonical accessor — populated by `extractIp(c)` in `normalizeRequest()`. Custom rate-limit `.by()` callbacks should read `req.ip`, not raw headers.
64
+
65
+ Trust-proxy mode (`trustProxy: true`) reads `X-Forwarded-For` + `X-Real-IP`. Without it, the direct socket address is used. Dev-mode `x-real-ip` injection from `@rudderjs/vite`'s `rudderjs:ip` plugin populates the header from `req.socket.remoteAddress` before universal-middleware converts to Web Request.
66
+
67
+ ### Controller views (@rudderjs/view integration)
68
+
69
+ When a route returns a `ViewResponse` (from `view('id', props)`), server-hono duck-types it via the `__rudder_view__` marker and resolves via Vike's `renderPage()`. The adapter also intercepts SPA-nav `*.pageContext.json` URL suffixes — but only for paths registered as controller routes, so Vike's own pages are unaffected.
70
+
71
+ ## Common Pitfalls
72
+
73
+ - **Mutating `req` expecting cross-call persistence.** Two `normalizeRequest(c)` calls per request means property sets on the first don't appear in the second. Store on `c` (Hono context) or use `req.raw.__custom`.
74
+ - **`trustProxy: true` without a trusted proxy chain.** Without a trusted proxy setting `X-Forwarded-For`, clients can spoof their IP by sending the header. Only set `trustProxy` when you're actually behind a proxy that strips client-supplied values.
75
+ - **Assuming Node APIs.** The fetch handler is WinterCG — it must work on Cloudflare Workers (no Node `http.Server`, no `fs` at top level). Lazy-load node built-ins inside functions if needed.
76
+ - **Installing a CORS middleware globally AND via server config.** The adapter's built-in CORS runs first. Additional `cors()` middleware via `m.use()` will run twice — usually benign but can double-set headers.
77
+ - **Request body on streaming endpoints.** `req.body` is parsed on first access. For streaming uploads, access `req.raw.body` (the underlying `ReadableStream`) instead — the parsed body caches the full contents.
78
+ - **Custom `.listen()` ports.** `app.fetch` is the WinterCG handler; it doesn't auto-listen. `+server.ts` exports `{ fetch: app.fetch }` for Vike. For Node without Vike, use `serve({ fetch: app.fetch, port })` from `@hono/node-server`.
79
+
80
+ ## Key Imports
81
+
82
+ ```ts
83
+ import { hono } from '@rudderjs/server-hono'
84
+
85
+ import type { HonoConfig } from '@rudderjs/server-hono'
86
+
87
+ // Standalone Node listener (no Vike)
88
+ import { serve } from '@hono/node-server'
89
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rudderjs/server-hono",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,7 +9,8 @@
9
9
  },
10
10
  "type": "module",
11
11
  "files": [
12
- "dist"
12
+ "dist",
13
+ "boost"
13
14
  ],
14
15
  "main": "./dist/index.js",
15
16
  "types": "./dist/index.d.ts",