@wooksjs/event-http 0.6.6 → 0.7.0
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.
- package/README.md +11 -45
- package/dist/index.cjs +1143 -963
- package/dist/index.d.ts +359 -303
- package/dist/index.mjs +1101 -917
- package/package.json +7 -7
- package/skills/wooksjs-event-http/SKILL.md +28 -21
- package/skills/wooksjs-event-http/core.md +83 -228
- package/skills/wooksjs-event-http/request.md +130 -146
- package/skills/wooksjs-event-http/response.md +166 -235
- package/skills/wooksjs-event-http/testing.md +150 -0
- package/skills/wooksjs-event-http/addons.md +0 -307
- package/skills/wooksjs-event-http/error-handling.md +0 -253
- package/skills/wooksjs-event-http/event-core.md +0 -562
- package/skills/wooksjs-event-http/routing.md +0 -412
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/event-http",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "@wooksjs/event-http",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"directory": "packages/event-http"
|
|
27
27
|
},
|
|
28
28
|
"bin": {
|
|
29
|
-
"
|
|
29
|
+
"wooksjs-event-http-skill": "scripts/setup-skills.js"
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
32
|
"dist",
|
|
@@ -47,14 +47,14 @@
|
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
49
|
"vitest": "^3.2.4",
|
|
50
|
-
"@wooksjs/event-core": "^0.
|
|
51
|
-
"wooks": "^0.
|
|
50
|
+
"@wooksjs/event-core": "^0.7.0",
|
|
51
|
+
"wooks": "^0.7.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"@prostojs/logger": "^0.4.3",
|
|
55
|
-
"@prostojs/router": "^0.3.
|
|
56
|
-
"@wooksjs/event-core": "^0.
|
|
57
|
-
"wooks": "^0.
|
|
55
|
+
"@prostojs/router": "^0.3.2",
|
|
56
|
+
"@wooksjs/event-core": "^0.7.0",
|
|
57
|
+
"wooks": "^0.7.0"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "rolldown -c ../../rolldown.config.mjs",
|
|
@@ -1,37 +1,44 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wooksjs-event-http
|
|
3
|
-
description:
|
|
3
|
+
description: Use this skill when working with @wooksjs/event-http — to create HTTP servers with createHttpApp(), register route handlers with app.get()/post()/put()/patch()/delete(), read request data with useRequest()/useHeaders()/useCookies()/useSearchParams()/useAuthorization()/useAccept(), control responses with useResponse() and HttpResponse (status, headers, cookies, cache control, streaming), throw HTTP errors with HttpError, test handlers with prepareTestHttpContext(), or integrate with existing Node.js servers via getServerCb().
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# @wooksjs/event-http
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
HTTP adapter for Wooks. Composable-based request handling where every piece of data is available on demand, typed, and cached per request. No middleware, no `req`/`res` parameters — just function calls.
|
|
9
9
|
|
|
10
10
|
## How to use this skill
|
|
11
11
|
|
|
12
12
|
Read the domain file that matches the task. Do not load all files — only what you need.
|
|
13
13
|
|
|
14
|
-
| Domain
|
|
15
|
-
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
| Response & status | [response.md](response.md) | `useResponse`, `useStatus`, `useSetHeaders`, `useSetHeader`, `useSetCookies`, `useSetCookie`, `useSetCacheControl`, content type, status hooks, cookie hooks |
|
|
21
|
-
| Error handling | [error-handling.md](error-handling.md) | `HttpError`, throwing errors, custom error bodies, error rendering, guard patterns |
|
|
22
|
-
| Addons (body, static, proxy) | [addons.md](addons.md) | `useBody` (body parsing), `serveFile` (static files), `useProxy` (request proxying) |
|
|
14
|
+
| Domain | File | Load when... |
|
|
15
|
+
| -------------------- | -------------------------- | -------------------------------------------------------------------------------------- |
|
|
16
|
+
| Core setup & routing | [core.md](core.md) | Creating an app, registering routes, starting a server, understanding the architecture |
|
|
17
|
+
| Request composables | [request.md](request.md) | Reading request data: headers, cookies, query params, body, authorization, IP |
|
|
18
|
+
| Response API | [response.md](response.md) | Setting status, headers, cookies, cache control, sending responses, error handling |
|
|
19
|
+
| Testing | [testing.md](testing.md) | Writing tests for handlers and composables with `prepareTestHttpContext` |
|
|
23
20
|
|
|
24
21
|
## Quick reference
|
|
25
22
|
|
|
26
23
|
```ts
|
|
27
|
-
import { createHttpApp
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
import { createHttpApp } from '@wooksjs/event-http'
|
|
25
|
+
|
|
26
|
+
// Composables (no arguments — context via AsyncLocalStorage)
|
|
27
|
+
import {
|
|
28
|
+
useRequest,
|
|
29
|
+
useResponse,
|
|
30
|
+
useHeaders,
|
|
31
|
+
useCookies,
|
|
32
|
+
useSearchParams,
|
|
33
|
+
useAuthorization,
|
|
34
|
+
useAccept,
|
|
35
|
+
useRouteParams,
|
|
36
|
+
useLogger,
|
|
37
|
+
} from '@wooksjs/event-http'
|
|
38
|
+
|
|
39
|
+
// Errors
|
|
40
|
+
import { HttpError } from '@wooksjs/event-http'
|
|
41
|
+
|
|
42
|
+
// Testing
|
|
43
|
+
import { prepareTestHttpContext } from '@wooksjs/event-http'
|
|
35
44
|
```
|
|
36
|
-
|
|
37
|
-
Key composables: `useRequest()`, `useResponse()`, `useRouteParams()`, `useHeaders()`, `useSetHeaders()`, `useCookies()`, `useSetCookies()`, `useSearchParams()`, `useAuthorization()`, `useAccept()`, `useSetCacheControl()`, `useStatus()`, `useBody()`, `useProxy()`.
|
|
@@ -1,297 +1,152 @@
|
|
|
1
|
-
# Core
|
|
1
|
+
# Core setup & routing — @wooksjs/event-http
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Creating an app, registering routes, server lifecycle, and architecture overview.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Concepts
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`@wooksjs/event-http` wraps a Node.js HTTP server with Wooks' composable architecture. Each incoming request gets its own `EventContext` (from `@wooksjs/event-core`), and handlers are plain functions that return their response. All request data is accessed through composables — on demand, typed, cached.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Key principles:
|
|
12
|
-
1. **Never mutate `req`** — Accumulate request context in the store instead.
|
|
13
|
-
2. **Never parse before needed** — Cookies, body, search params are only parsed when a composable is first called.
|
|
14
|
-
3. **No middleware sprawl** — Composable functions replace middleware. Each one is a focused, importable utility.
|
|
9
|
+
The adapter creates context, seeds it with the `IncomingMessage` and `HttpResponse`, looks up routes, and runs handlers. Handlers never receive `req`/`res` parameters.
|
|
15
10
|
|
|
16
11
|
## Installation
|
|
17
12
|
|
|
18
13
|
```bash
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Creating an HTTP App
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
import { createHttpApp } from '@wooksjs/event-http'
|
|
26
|
-
|
|
27
|
-
const app = createHttpApp()
|
|
28
|
-
|
|
29
|
-
app.get('/hello', () => 'Hello World!')
|
|
30
|
-
|
|
31
|
-
app.listen(3000, () => {
|
|
32
|
-
console.log('Server running on port 3000')
|
|
33
|
-
})
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
`createHttpApp(opts?, wooks?)` returns a `WooksHttp` instance. Options:
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
interface TWooksHttpOptions {
|
|
40
|
-
logger?: TConsoleBase // custom logger
|
|
41
|
-
eventOptions?: TEventOptions // event-level logger config
|
|
42
|
-
onNotFound?: TWooksHandler // custom 404 handler
|
|
43
|
-
router?: {
|
|
44
|
-
ignoreTrailingSlash?: boolean // treat /path and /path/ as the same
|
|
45
|
-
ignoreCase?: boolean // case-insensitive matching
|
|
46
|
-
cacheLimit?: number // max cached parsed routes
|
|
47
|
-
}
|
|
48
|
-
requestLimits?: { // app-level body limits (overridable per-request)
|
|
49
|
-
maxCompressed?: number // default: 1 MB
|
|
50
|
-
maxInflated?: number // default: 10 MB
|
|
51
|
-
maxRatio?: number // default: 100 (zip-bomb protection)
|
|
52
|
-
readTimeoutMs?: number // default: 10 000 ms
|
|
53
|
-
}
|
|
54
|
-
}
|
|
14
|
+
pnpm add @wooksjs/event-http
|
|
55
15
|
```
|
|
56
16
|
|
|
57
|
-
|
|
17
|
+
Peer dependencies: `@wooksjs/event-core`, `wooks`, `@prostojs/router`, `@prostojs/logger`.
|
|
58
18
|
|
|
59
|
-
|
|
60
|
-
const app = createHttpApp({
|
|
61
|
-
requestLimits: {
|
|
62
|
-
maxCompressed: 50 * 1024 * 1024, // 50 MB
|
|
63
|
-
maxInflated: 100 * 1024 * 1024, // 100 MB
|
|
64
|
-
maxRatio: 200,
|
|
65
|
-
},
|
|
66
|
-
})
|
|
67
|
-
```
|
|
19
|
+
## API Reference
|
|
68
20
|
|
|
69
|
-
|
|
21
|
+
### `createHttpApp(opts?): WooksHttp`
|
|
70
22
|
|
|
71
|
-
|
|
23
|
+
Creates and returns a `WooksHttp` instance.
|
|
72
24
|
|
|
73
25
|
```ts
|
|
74
|
-
import http from 'http'
|
|
75
26
|
import { createHttpApp } from '@wooksjs/event-http'
|
|
76
27
|
|
|
77
28
|
const app = createHttpApp()
|
|
78
29
|
app.get('/hello', () => 'Hello World!')
|
|
79
|
-
|
|
80
|
-
const server = http.createServer(app.getServerCb())
|
|
81
|
-
server.listen(3000)
|
|
30
|
+
app.listen(3000)
|
|
82
31
|
```
|
|
83
32
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
When a request arrives, the adapter creates an HTTP-specific event context:
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
Request arrives (req, res)
|
|
90
|
-
→ createHttpContext({ req, res }, options)
|
|
91
|
-
→ AsyncLocalStorage.run(httpContextStore, handler)
|
|
92
|
-
→ router matches path → handler runs
|
|
93
|
-
→ handler calls useRequest(), useCookies(), etc.
|
|
94
|
-
→ each composable calls useHttpContext()
|
|
95
|
-
→ reads/writes the HTTP context store via init(), get(), set()
|
|
96
|
-
```
|
|
33
|
+
**Options (`TWooksHttpOptions`):**
|
|
97
34
|
|
|
98
|
-
|
|
35
|
+
| Option | Type | Description |
|
|
36
|
+
| --------------- | -------------------------- | ------------------------------------------------------------- |
|
|
37
|
+
| `logger` | `TConsoleBase` | Custom logger instance |
|
|
38
|
+
| `onNotFound` | `TWooksHandler` | Handler called when no route matches (default: 404 HttpError) |
|
|
39
|
+
| `router` | router options | Custom router configuration |
|
|
40
|
+
| `requestLimits` | `Omit<TRequestLimits, 'perRequest'>` | Default body size/timeout limits for all requests |
|
|
41
|
+
| `responseClass` | `typeof WooksHttpResponse` | Custom response subclass (default: `WooksHttpResponse`) |
|
|
42
|
+
| `defaultHeaders` | `Record<string, string \| string[]>` | Default headers applied to every response (e.g. from `securityHeaders()`) |
|
|
99
43
|
|
|
100
|
-
|
|
44
|
+
### Route registration
|
|
101
45
|
|
|
102
46
|
```ts
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
response?: { responded: boolean } // response sent flag
|
|
112
|
-
status?: { code: EHttpStatusCode } // response status code
|
|
113
|
-
}
|
|
47
|
+
app.get(path, handler)
|
|
48
|
+
app.post(path, handler)
|
|
49
|
+
app.put(path, handler)
|
|
50
|
+
app.patch(path, handler)
|
|
51
|
+
app.delete(path, handler)
|
|
52
|
+
app.head(path, handler)
|
|
53
|
+
app.options(path, handler)
|
|
54
|
+
app.all(path, handler) // matches any HTTP method
|
|
114
55
|
```
|
|
115
56
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
### Extending the HTTP Store for Custom Composables
|
|
119
|
-
|
|
120
|
-
When creating custom composables for HTTP, extend the store type via the generic parameter on `useHttpContext`:
|
|
57
|
+
Handlers are plain functions. Return value becomes the response body:
|
|
121
58
|
|
|
122
59
|
```ts
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
parsedToken?: { userId: string; role: string } | null
|
|
128
|
-
isAdmin?: boolean
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export function useMyFeature() {
|
|
133
|
-
const { store } = useHttpContext<TMyStore>()
|
|
134
|
-
const { init } = store('myFeature')
|
|
135
|
-
|
|
136
|
-
const parsedToken = () =>
|
|
137
|
-
init('parsedToken', () => {
|
|
138
|
-
const { authRawCredentials, isBearer } = useAuthorization()
|
|
139
|
-
if (!isBearer()) return null
|
|
140
|
-
return decodeToken(authRawCredentials()!)
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
const isAdmin = () =>
|
|
144
|
-
init('isAdmin', () => parsedToken()?.role === 'admin')
|
|
145
|
-
|
|
146
|
-
return { parsedToken, isAdmin }
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
For the full context store API and more composable patterns, see [event-core.md](event-core.md).
|
|
151
|
-
|
|
152
|
-
## Server Lifecycle
|
|
60
|
+
app.get('/users/:id', () => {
|
|
61
|
+
const { params } = useRouteParams<{ id: string }>()
|
|
62
|
+
return { id: params.id } // → 200 application/json
|
|
63
|
+
})
|
|
153
64
|
|
|
154
|
-
|
|
65
|
+
app.post('/users', async () => {
|
|
66
|
+
const { parseBody } = useBody() // from @wooksjs/http-body
|
|
67
|
+
const user = await parseBody<{ name: string }>()
|
|
68
|
+
return { created: user.name } // → 201 application/json (POST auto-status)
|
|
69
|
+
})
|
|
70
|
+
```
|
|
155
71
|
|
|
156
|
-
|
|
72
|
+
### Server lifecycle
|
|
157
73
|
|
|
158
74
|
```ts
|
|
75
|
+
// Start server
|
|
159
76
|
await app.listen(3000)
|
|
160
77
|
await app.listen(3000, '0.0.0.0')
|
|
161
|
-
await app.listen({ port: 3000, host: '0.0.0.0' })
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### `close(server?)`
|
|
165
78
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
```ts
|
|
169
|
-
await app.close()
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### `getServer()`
|
|
173
|
-
|
|
174
|
-
Returns the underlying `http.Server` instance (only available after `listen()`):
|
|
175
|
-
|
|
176
|
-
```ts
|
|
177
|
-
const server = app.getServer()
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### `attachServer(server)`
|
|
181
|
-
|
|
182
|
-
Attaches an external server so `close()` can stop it:
|
|
183
|
-
|
|
184
|
-
```ts
|
|
79
|
+
// Use with existing server
|
|
80
|
+
import http from 'http'
|
|
185
81
|
const server = http.createServer(app.getServerCb())
|
|
186
|
-
app.attachServer(server)
|
|
187
82
|
server.listen(3000)
|
|
188
|
-
|
|
83
|
+
app.attachServer(server)
|
|
84
|
+
|
|
85
|
+
// Stop server
|
|
86
|
+
await app.close()
|
|
189
87
|
```
|
|
190
88
|
|
|
191
89
|
### `getServerCb()`
|
|
192
90
|
|
|
193
|
-
Returns
|
|
91
|
+
Returns a `(req, res) => void` callback for use with any Node.js HTTP server:
|
|
194
92
|
|
|
195
93
|
```ts
|
|
196
94
|
const cb = app.getServerCb()
|
|
197
95
|
http.createServer(cb).listen(3000)
|
|
198
|
-
// or with https
|
|
199
|
-
https.createServer(sslOpts, cb).listen(443)
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Sharing Router Between Adapters
|
|
203
|
-
|
|
204
|
-
Multiple adapters can share the same Wooks router:
|
|
205
|
-
|
|
206
|
-
```ts
|
|
207
|
-
import { Wooks } from 'wooks'
|
|
208
|
-
import { createHttpApp } from '@wooksjs/event-http'
|
|
209
|
-
|
|
210
|
-
const wooks = new Wooks()
|
|
211
|
-
const app1 = createHttpApp({}, wooks)
|
|
212
|
-
const app2 = createHttpApp({}, wooks) // shares the same routes
|
|
96
|
+
// or with https, http2, etc.
|
|
213
97
|
```
|
|
214
98
|
|
|
215
|
-
|
|
99
|
+
## Routing
|
|
216
100
|
|
|
217
|
-
|
|
218
|
-
const app1 = createHttpApp()
|
|
219
|
-
const app2 = createHttpApp({}, app1) // shares app1's router
|
|
220
|
-
```
|
|
101
|
+
Built on [`@prostojs/router`](https://github.com/prostojs/router). Supports:
|
|
221
102
|
|
|
222
|
-
|
|
103
|
+
- Static routes: `/api/users`
|
|
104
|
+
- Parametric routes: `/users/:id`
|
|
105
|
+
- Wildcards: `/static/*`
|
|
106
|
+
- Multiple wildcards: `/static/*/assets/*`
|
|
107
|
+
- Regex constraints: `/api/time/:hours(\\d{2})h:minutes(\\d{2})m`
|
|
108
|
+
- Regex wildcards: `/static/*(\\d+)`
|
|
223
109
|
|
|
224
|
-
|
|
110
|
+
Route params accessed via `useRouteParams()`:
|
|
225
111
|
|
|
226
112
|
```ts
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
Inside a handler, use the event-scoped logger:
|
|
233
|
-
|
|
234
|
-
```ts
|
|
235
|
-
import { useEventLogger } from '@wooksjs/event-core'
|
|
236
|
-
|
|
237
|
-
app.get('/process', () => {
|
|
238
|
-
const logger = useEventLogger('my-handler')
|
|
239
|
-
logger.log('Processing request') // tagged with event ID
|
|
240
|
-
return 'ok'
|
|
113
|
+
app.get('/users/:id', () => {
|
|
114
|
+
const { params } = useRouteParams<{ id: string }>()
|
|
115
|
+
return { userId: params.id }
|
|
241
116
|
})
|
|
242
117
|
```
|
|
243
118
|
|
|
244
|
-
##
|
|
119
|
+
## Auto-status
|
|
245
120
|
|
|
246
|
-
|
|
121
|
+
When no explicit status is set, it's inferred from the HTTP method and response body:
|
|
247
122
|
|
|
248
|
-
|
|
249
|
-
|
|
123
|
+
| Method | With body | Without body |
|
|
124
|
+
| ------ | ------------ | -------------- |
|
|
125
|
+
| GET | 200 OK | 204 No Content |
|
|
126
|
+
| POST | 201 Created | 204 No Content |
|
|
127
|
+
| PUT | 201 Created | 204 No Content |
|
|
128
|
+
| PATCH | 202 Accepted | 204 No Content |
|
|
129
|
+
| DELETE | 202 Accepted | 204 No Content |
|
|
250
130
|
|
|
251
|
-
|
|
252
|
-
url: '/users/42',
|
|
253
|
-
method: 'GET',
|
|
254
|
-
headers: { authorization: 'Bearer test-token' },
|
|
255
|
-
params: { id: '42' },
|
|
256
|
-
})
|
|
131
|
+
## Handler chain
|
|
257
132
|
|
|
258
|
-
|
|
259
|
-
const { get } = useRouteParams()
|
|
260
|
-
console.log(get('id')) // '42'
|
|
261
|
-
|
|
262
|
-
const { isBearer } = useAuthorization()
|
|
263
|
-
console.log(isBearer()) // true
|
|
264
|
-
})
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### `prepareTestHttpContext(options)`
|
|
133
|
+
Multiple handlers can be registered for the same route. If one throws, the next is tried:
|
|
268
134
|
|
|
269
135
|
```ts
|
|
270
|
-
|
|
271
|
-
url: string
|
|
272
|
-
method?: string // default: 'GET'
|
|
273
|
-
headers?: Record<string, string>
|
|
274
|
-
params?: Record<string, string | string[]>
|
|
275
|
-
requestLimits?: TRequestLimits // app-level body limits for testing
|
|
276
|
-
cachedContext?: {
|
|
277
|
-
cookies?: Record<string, string | null>
|
|
278
|
-
authorization?: TAuthCache
|
|
279
|
-
body?: unknown // pre-parsed body
|
|
280
|
-
rawBody?: string | Buffer | Promise<Buffer>
|
|
281
|
-
raw?: Partial<THttpContextStore> // raw store sections
|
|
282
|
-
}
|
|
283
|
-
}
|
|
136
|
+
app.get('/resource', authHandler, mainHandler)
|
|
284
137
|
```
|
|
285
138
|
|
|
139
|
+
If all handlers throw, the last error is sent as the response.
|
|
140
|
+
|
|
286
141
|
## Best Practices
|
|
287
142
|
|
|
288
|
-
-
|
|
289
|
-
-
|
|
290
|
-
-
|
|
291
|
-
-
|
|
143
|
+
- Return values directly — the framework handles serialization and status codes
|
|
144
|
+
- Use `HttpError` for error responses: `throw new HttpError(404)` or `throw new HttpError(400, 'Invalid input')`
|
|
145
|
+
- Use `useResponse()` only when you need explicit control over headers, cookies, or status
|
|
146
|
+
- For `getServerCb()`, call `attachServer(server)` if you want `close()` to work
|
|
292
147
|
|
|
293
148
|
## Gotchas
|
|
294
149
|
|
|
295
|
-
-
|
|
296
|
-
- `listen()` returns a
|
|
297
|
-
-
|
|
150
|
+
- Handlers receive no arguments — all data comes from composables
|
|
151
|
+
- `listen()` returns a Promise — `await` it or handle rejection
|
|
152
|
+
- `getServerCb()` doesn't automatically attach the server — call `attachServer()` if needed
|