@moostjs/event-http 0.5.32 → 0.6.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 +67 -3
- package/dist/index.cjs +261 -83
- package/dist/index.d.ts +123 -22
- package/dist/index.mjs +248 -86
- package/package.json +40 -34
- package/scripts/setup-skills.js +76 -0
- package/skills/moostjs-event-http/SKILL.md +32 -0
- package/skills/moostjs-event-http/auth.md +275 -0
- package/skills/moostjs-event-http/core.md +193 -0
- package/skills/moostjs-event-http/request.md +230 -0
- package/skills/moostjs-event-http/response.md +287 -0
- package/skills/moostjs-event-http/routing.md +210 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Routing & handlers — @moostjs/event-http
|
|
2
|
+
|
|
3
|
+
> Defining HTTP routes, methods, parameters, wildcards, and handler return values.
|
|
4
|
+
|
|
5
|
+
## Concepts
|
|
6
|
+
|
|
7
|
+
Every HTTP endpoint is defined by a method decorator (`@Get`, `@Post`, etc.) on a controller method. The decorator specifies the HTTP method and optional path. Route parameters (`:param`), wildcards (`*`), and regex constraints provide flexible URL matching. Controllers group related handlers under a shared prefix.
|
|
8
|
+
|
|
9
|
+
## API Reference
|
|
10
|
+
|
|
11
|
+
### HTTP method decorators
|
|
12
|
+
|
|
13
|
+
All imported from `@moostjs/event-http`:
|
|
14
|
+
|
|
15
|
+
| Decorator | HTTP Method | Usage |
|
|
16
|
+
|-----------|-------------|-------|
|
|
17
|
+
| `@Get(path?)` | GET | `@Get('users/:id')` |
|
|
18
|
+
| `@Post(path?)` | POST | `@Post('users')` |
|
|
19
|
+
| `@Put(path?)` | PUT | `@Put('users/:id')` |
|
|
20
|
+
| `@Delete(path?)` | DELETE | `@Delete('users/:id')` |
|
|
21
|
+
| `@Patch(path?)` | PATCH | `@Patch('users/:id')` |
|
|
22
|
+
| `@All(path?)` | All methods | `@All('proxy/*')` |
|
|
23
|
+
| `@HttpMethod(method, path?)` | Any method | `@HttpMethod('OPTIONS', '')` |
|
|
24
|
+
| `@Upgrade(path?)` | UPGRADE | `@Upgrade('/ws')` |
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { Get, Post, Put, Delete, Patch, All, HttpMethod, Upgrade } from '@moostjs/event-http'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### `@HttpMethod(method, path?)`
|
|
31
|
+
|
|
32
|
+
The base decorator — all convenience decorators (`@Get`, `@Post`, etc.) call this internally.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
@HttpMethod('HEAD', 'health')
|
|
36
|
+
healthCheck() { /* HEAD /health */ }
|
|
37
|
+
|
|
38
|
+
@HttpMethod('OPTIONS', '')
|
|
39
|
+
cors() { /* OPTIONS / */ }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Valid methods: `'GET'`, `'PUT'`, `'POST'`, `'PATCH'`, `'DELETE'`, `'HEAD'`, `'OPTIONS'`, `'UPGRADE'`, `'*'`
|
|
43
|
+
|
|
44
|
+
### `@Upgrade(path?)`
|
|
45
|
+
|
|
46
|
+
Registers an UPGRADE route for WebSocket handshakes. Use with `@moostjs/event-ws`:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
@Upgrade('/ws')
|
|
50
|
+
handleUpgrade(ws: WooksWs) {
|
|
51
|
+
return ws.upgrade()
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Route parameters — `@Param` and `@Params`
|
|
56
|
+
|
|
57
|
+
Imported from `moost` (not from `@moostjs/event-http`):
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { Controller, Param, Params } from 'moost'
|
|
61
|
+
import { Get } from '@moostjs/event-http'
|
|
62
|
+
|
|
63
|
+
@Controller('users')
|
|
64
|
+
class UserController {
|
|
65
|
+
@Get(':id')
|
|
66
|
+
find(@Param('id') id: string) {
|
|
67
|
+
return { id } // GET /users/123
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Get(':type/:type/:id')
|
|
71
|
+
getAsset(@Params() params: { type: string[], id: string }) {
|
|
72
|
+
return params
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Common Patterns
|
|
78
|
+
|
|
79
|
+
### Pattern: Path defaults
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
@Get() // path = method name, e.g. GET /getUsers
|
|
83
|
+
getUsers() {}
|
|
84
|
+
|
|
85
|
+
@Get('') // path = controller root, e.g. GET /
|
|
86
|
+
root() {}
|
|
87
|
+
|
|
88
|
+
@Get('list') // explicit path, e.g. GET /list
|
|
89
|
+
listItems() {}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Pattern: Multiple parameters
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// Slash-separated: /flights/SFO/LAX
|
|
96
|
+
@Get('flights/:from/:to')
|
|
97
|
+
getFlight(@Param('from') from: string, @Param('to') to: string) {}
|
|
98
|
+
|
|
99
|
+
// Hyphen-separated: /dates/2024-01-15
|
|
100
|
+
@Get('dates/:year-:month-:day')
|
|
101
|
+
getDate(
|
|
102
|
+
@Param('year') year: string,
|
|
103
|
+
@Param('month') month: string,
|
|
104
|
+
@Param('day') day: string,
|
|
105
|
+
) {}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Pattern: Regex-constrained parameters
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
// Only matches two-digit hours and minutes: /time/09h30m
|
|
112
|
+
@Get('time/:hours(\\d{2})h:minutes(\\d{2})m')
|
|
113
|
+
getTime(@Param('hours') hours: string, @Param('minutes') minutes: string) {}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Pattern: Repeated parameters (arrays)
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
// /rgb/255/128/0 -> color = ['255', '128', '0']
|
|
120
|
+
@Get('rgb/:color/:color/:color')
|
|
121
|
+
getRgb(@Param('color') color: string[]) {}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Pattern: Wildcards
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
@Controller('static')
|
|
128
|
+
class StaticController {
|
|
129
|
+
@Get('*')
|
|
130
|
+
handleAll(@Param('*') path: string) {}
|
|
131
|
+
|
|
132
|
+
@Get('*.js')
|
|
133
|
+
handleJS(@Param('*') name: string) {}
|
|
134
|
+
|
|
135
|
+
// Multiple wildcards -> array
|
|
136
|
+
@Get('*/test/*')
|
|
137
|
+
handleTest(@Param('*') paths: string[]) {}
|
|
138
|
+
|
|
139
|
+
// Regex on wildcard: only digits
|
|
140
|
+
@Get('*(\\d+)')
|
|
141
|
+
handleNumbers(@Param('*') path: string) {}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Pattern: Controller prefix
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { Controller } from 'moost'
|
|
149
|
+
|
|
150
|
+
@Controller('api/v1/users')
|
|
151
|
+
class UserController {
|
|
152
|
+
@Get('') // GET /api/v1/users
|
|
153
|
+
list() {}
|
|
154
|
+
|
|
155
|
+
@Get(':id') // GET /api/v1/users/123
|
|
156
|
+
find() {}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Pattern: Nested controllers
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { Controller, ImportController } from 'moost'
|
|
164
|
+
|
|
165
|
+
@Controller('api')
|
|
166
|
+
class ApiController {
|
|
167
|
+
@ImportController(() => UserController)
|
|
168
|
+
users!: UserController
|
|
169
|
+
|
|
170
|
+
@ImportController(() => ProductController)
|
|
171
|
+
products!: ProductController
|
|
172
|
+
}
|
|
173
|
+
// Routes: GET /api/users/..., GET /api/products/...
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Handler return values
|
|
177
|
+
|
|
178
|
+
Whatever the handler returns becomes the response body:
|
|
179
|
+
|
|
180
|
+
| Return type | Content-Type |
|
|
181
|
+
|-------------|--------------|
|
|
182
|
+
| `string` | `text/plain` |
|
|
183
|
+
| object / array | `application/json` |
|
|
184
|
+
| `ReadableStream` | streamed |
|
|
185
|
+
| fetch `Response` | forwarded as-is |
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
@Get('text')
|
|
189
|
+
getText() { return 'Hello!' } // text/plain
|
|
190
|
+
|
|
191
|
+
@Get('json')
|
|
192
|
+
getJson() { return { message: 'Hi' } } // application/json
|
|
193
|
+
|
|
194
|
+
@Get('data')
|
|
195
|
+
async getData() { return await fetchFromDb() } // async works
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Best Practices
|
|
199
|
+
|
|
200
|
+
- Use `@Get('')` (empty string) for the controller root path, not `@Get()` (which uses the method name)
|
|
201
|
+
- Keep controller prefixes as REST resource names: `@Controller('users')`, `@Controller('products')`
|
|
202
|
+
- Use `@Param` for individual route parameters, `@Params` when you need the full params object
|
|
203
|
+
- Prefer convenience decorators (`@Get`, `@Post`) over `@HttpMethod` for standard methods
|
|
204
|
+
|
|
205
|
+
## Gotchas
|
|
206
|
+
|
|
207
|
+
- `@Get()` without arguments uses the **method name** as the path — this is rarely what you want
|
|
208
|
+
- Route parameters are always strings — use pipes to transform to numbers/booleans
|
|
209
|
+
- An explicit double slash `//` at the end of a path forces the URL to end with a trailing slash
|
|
210
|
+
- Query parameters are not part of the route path — use `@Query()` to extract them
|