@navios/core 0.4.0 → 0.5.1
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 +95 -2
- package/docs/README.md +310 -3
- package/docs/adapters.md +308 -0
- package/docs/application-setup.md +524 -0
- package/docs/attributes.md +689 -0
- package/docs/controllers.md +373 -0
- package/docs/endpoints.md +444 -0
- package/docs/exceptions.md +316 -0
- package/docs/guards.md +550 -0
- package/docs/modules.md +377 -0
- package/docs/quick-start.md +295 -0
- package/docs/services.md +427 -0
- package/docs/testing.md +704 -0
- package/lib/_tsup-dts-rollup.d.mts +310 -239
- package/lib/_tsup-dts-rollup.d.ts +310 -239
- package/lib/index.d.mts +51 -28
- package/lib/index.d.ts +51 -28
- package/lib/index.js +633 -1072
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +631 -1064
- package/lib/index.mjs.map +1 -1
- package/package.json +5 -9
- package/project.json +9 -1
- package/src/__tests__/config.service.spec.mts +11 -9
- package/src/__tests__/controller.spec.mts +0 -1
- package/src/config/config.service.mts +2 -2
- package/src/decorators/controller.decorator.mts +1 -1
- package/src/decorators/endpoint.decorator.mts +2 -2
- package/src/decorators/header.decorator.mts +1 -1
- package/src/decorators/multipart.decorator.mts +1 -2
- package/src/decorators/stream.decorator.mts +2 -3
- package/src/factories/endpoint-adapter.factory.mts +21 -0
- package/src/factories/http-adapter.factory.mts +20 -0
- package/src/factories/index.mts +6 -0
- package/src/factories/multipart-adapter.factory.mts +21 -0
- package/src/factories/reply.factory.mts +21 -0
- package/src/factories/request.factory.mts +21 -0
- package/src/factories/stream-adapter.factory.mts +20 -0
- package/src/index.mts +1 -1
- package/src/interfaces/abstract-execution-context.inteface.mts +13 -0
- package/src/interfaces/abstract-http-adapter.interface.mts +20 -0
- package/src/interfaces/abstract-http-cors-options.interface.mts +59 -0
- package/src/interfaces/abstract-http-handler-adapter.interface.mts +13 -0
- package/src/interfaces/abstract-http-listen-options.interface.mts +4 -0
- package/src/interfaces/can-activate.mts +4 -2
- package/src/interfaces/http-header.mts +18 -0
- package/src/interfaces/index.mts +6 -0
- package/src/logger/console-logger.service.mts +28 -44
- package/src/logger/index.mts +1 -2
- package/src/logger/logger.service.mts +9 -128
- package/src/logger/logger.tokens.mts +21 -0
- package/src/metadata/handler.metadata.mts +7 -5
- package/src/navios.application.mts +65 -172
- package/src/navios.environment.mts +30 -0
- package/src/navios.factory.mts +53 -12
- package/src/services/guard-runner.service.mts +19 -9
- package/src/services/index.mts +0 -2
- package/src/services/module-loader.service.mts +4 -3
- package/src/tokens/endpoint-adapter.token.mts +8 -0
- package/src/tokens/execution-context.token.mts +2 -2
- package/src/tokens/http-adapter.token.mts +8 -0
- package/src/tokens/index.mts +4 -1
- package/src/tokens/multipart-adapter.token.mts +8 -0
- package/src/tokens/reply.token.mts +1 -5
- package/src/tokens/request.token.mts +1 -7
- package/src/tokens/stream-adapter.token.mts +8 -0
- package/docs/recipes/prisma.md +0 -60
- package/e2e/endpoints/get.spec.mts +0 -97
- package/e2e/endpoints/post.spec.mts +0 -113
- package/examples/simple-test/api/index.mts +0 -64
- package/examples/simple-test/config/config.service.mts +0 -14
- package/examples/simple-test/config/configuration.mts +0 -7
- package/examples/simple-test/index.mts +0 -16
- package/examples/simple-test/src/acl/acl-modern.guard.mts +0 -15
- package/examples/simple-test/src/acl/acl.guard.mts +0 -14
- package/examples/simple-test/src/acl/app.guard.mts +0 -27
- package/examples/simple-test/src/acl/one-more.guard.mts +0 -15
- package/examples/simple-test/src/acl/public.attribute.mts +0 -21
- package/examples/simple-test/src/app.module.mts +0 -9
- package/examples/simple-test/src/user/user.controller.mts +0 -72
- package/examples/simple-test/src/user/user.module.mts +0 -14
- package/examples/simple-test/src/user/user.service.mts +0 -14
- package/src/adapters/endpoint-adapter.service.mts +0 -72
- package/src/adapters/handler-adapter.interface.mts +0 -21
- package/src/adapters/index.mts +0 -4
- package/src/adapters/multipart-adapter.service.mts +0 -135
- package/src/adapters/stream-adapter.service.mts +0 -91
- package/src/logger/logger.factory.mts +0 -36
- package/src/logger/pino-wrapper.mts +0 -64
- package/src/services/controller-adapter.service.mts +0 -124
- package/src/services/execution-context.mts +0 -54
- package/src/tokens/application.token.mts +0 -9
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
# Endpoints
|
|
2
|
+
|
|
3
|
+
Endpoints in Navios are HTTP routes defined as methods in controllers. They are decorated with the `@Endpoint()` decorator and specify how to handle incoming HTTP requests.
|
|
4
|
+
|
|
5
|
+
## What is an Endpoint?
|
|
6
|
+
|
|
7
|
+
An endpoint is a controller method that handles a specific HTTP request. It defines:
|
|
8
|
+
|
|
9
|
+
- HTTP method (GET, POST, PUT, DELETE, etc.)
|
|
10
|
+
- URL pattern with optional parameters
|
|
11
|
+
- Request/response schemas for validation
|
|
12
|
+
- Business logic to process the request
|
|
13
|
+
|
|
14
|
+
## Creating Endpoints
|
|
15
|
+
|
|
16
|
+
### Basic Endpoint
|
|
17
|
+
|
|
18
|
+
First, define your endpoint using `@navios/builder`:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// api/users.ts
|
|
22
|
+
import { builder } from '@navios/builder'
|
|
23
|
+
|
|
24
|
+
import { z } from 'zod'
|
|
25
|
+
|
|
26
|
+
const UserSchema = z.object({
|
|
27
|
+
id: z.string(),
|
|
28
|
+
name: z.string(),
|
|
29
|
+
email: z.string().email(),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export const api = builder()
|
|
33
|
+
|
|
34
|
+
export const getUsersEndpoint = api.declareEndpoint({
|
|
35
|
+
method: 'GET',
|
|
36
|
+
url: '/users',
|
|
37
|
+
responseSchema: z.array(UserSchema),
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then use it in your controller:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import type { EndpointParams } from '@navios/core'
|
|
45
|
+
|
|
46
|
+
import { Controller, Endpoint } from '@navios/core'
|
|
47
|
+
|
|
48
|
+
import { getUsersEndpoint } from '../api/users.js'
|
|
49
|
+
|
|
50
|
+
// controllers/user.controller.ts
|
|
51
|
+
|
|
52
|
+
@Controller()
|
|
53
|
+
export class UserController {
|
|
54
|
+
@Endpoint(getUsersEndpoint)
|
|
55
|
+
async getUsers(params: EndpointParams<typeof getUsersEndpoint>) {
|
|
56
|
+
return [
|
|
57
|
+
{ id: '1', name: 'John', email: 'john@example.com' },
|
|
58
|
+
{ id: '2', name: 'Jane', email: 'jane@example.com' },
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> **Note**: Always use `@navios/builder` to declare endpoints instead of passing configuration objects directly to `@Endpoint()`. This ensures type safety and better maintainability.
|
|
65
|
+
|
|
66
|
+
### Endpoint with Path Parameters
|
|
67
|
+
|
|
68
|
+
Define the endpoint with path parameters:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// api/users.ts
|
|
72
|
+
export const getUserByIdEndpoint = api.declareEndpoint({
|
|
73
|
+
method: 'GET',
|
|
74
|
+
url: '/users/$id',
|
|
75
|
+
responseSchema: UserSchema,
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use it in your controller:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
@Controller()
|
|
83
|
+
export class UserController {
|
|
84
|
+
@Endpoint(getUserByIdEndpoint)
|
|
85
|
+
async getUserById(params: EndpointParams<typeof getUserByIdEndpoint>) {
|
|
86
|
+
// params.id is automatically extracted from the URL
|
|
87
|
+
return { id: params.id, name: 'John', email: 'john@example.com' }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Endpoint with Query Parameters
|
|
93
|
+
|
|
94
|
+
Define the endpoint with query parameters:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// api/users.ts
|
|
98
|
+
const QuerySchema = z.object({
|
|
99
|
+
page: z.coerce.number().min(1).default(1),
|
|
100
|
+
limit: z.coerce.number().min(1).max(100).default(10),
|
|
101
|
+
search: z.string().optional(),
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
export const getUsersWithQueryEndpoint = api.declareEndpoint({
|
|
105
|
+
method: 'GET',
|
|
106
|
+
url: '/users',
|
|
107
|
+
querySchema: QuerySchema,
|
|
108
|
+
responseSchema: z.array(UserSchema),
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Use it in your controller:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
@Controller()
|
|
116
|
+
export class UserController {
|
|
117
|
+
@Endpoint(getUsersWithQueryEndpoint)
|
|
118
|
+
async getUsers(params: EndpointParams<typeof getUsersWithQueryEndpoint>) {
|
|
119
|
+
// query parameters are validated and typed
|
|
120
|
+
const { page, limit, search } = params.query
|
|
121
|
+
return this.userService.findMany({ page, limit, search })
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Endpoint with Request Body
|
|
127
|
+
|
|
128
|
+
Define the endpoint with request body:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// api/users.ts
|
|
132
|
+
const CreateUserSchema = z.object({
|
|
133
|
+
name: z.string().min(1),
|
|
134
|
+
email: z.string().email(),
|
|
135
|
+
age: z.number().min(0).max(120),
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
export const createUserEndpoint = api.declareEndpoint({
|
|
139
|
+
method: 'POST',
|
|
140
|
+
url: '/users',
|
|
141
|
+
requestSchema: CreateUserSchema,
|
|
142
|
+
responseSchema: UserSchema,
|
|
143
|
+
})
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Use it in your controller:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
@Controller()
|
|
150
|
+
export class UserController {
|
|
151
|
+
@Endpoint(createUserEndpoint)
|
|
152
|
+
async createUser(params: EndpointParams<typeof createUserEndpoint>) {
|
|
153
|
+
// body is validated against CreateUserSchema
|
|
154
|
+
return this.userService.create(params.data)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Endpoint Configuration
|
|
160
|
+
|
|
161
|
+
### Using `@navios/builder` (Recommended)
|
|
162
|
+
|
|
163
|
+
The `@Endpoint()` decorator should receive an endpoint definition created with `@navios/builder`. This approach provides better type safety and maintainability:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { builder } from '@navios/builder'
|
|
167
|
+
|
|
168
|
+
import { z } from 'zod'
|
|
169
|
+
|
|
170
|
+
export const api = builder()
|
|
171
|
+
|
|
172
|
+
export const myEndpoint = api.declareEndpoint({
|
|
173
|
+
method: 'GET', // 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'
|
|
174
|
+
url: '/users/$id', // URL pattern with url parameters
|
|
175
|
+
responseSchema: z.object({
|
|
176
|
+
id: z.string(),
|
|
177
|
+
name: z.string(),
|
|
178
|
+
}),
|
|
179
|
+
requestSchema: z.object({
|
|
180
|
+
// Optional: for POST/PUT/PATCH
|
|
181
|
+
name: z.string(),
|
|
182
|
+
email: z.string().email(),
|
|
183
|
+
}),
|
|
184
|
+
querySchema: z.object({
|
|
185
|
+
// Optional: for query parameters
|
|
186
|
+
page: z.coerce.number().default(1),
|
|
187
|
+
search: z.string().optional(),
|
|
188
|
+
}),
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Endpoint Definition Properties
|
|
193
|
+
|
|
194
|
+
When using `api.declareEndpoint()`, you can specify:
|
|
195
|
+
|
|
196
|
+
#### `method` (required)
|
|
197
|
+
|
|
198
|
+
- **Type**: `HttpMethod` ('GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS')
|
|
199
|
+
- **Description**: HTTP method for the endpoint
|
|
200
|
+
|
|
201
|
+
#### `url` (required)
|
|
202
|
+
|
|
203
|
+
- **Type**: `string`
|
|
204
|
+
- **Description**: URL pattern with optional parameters (`:param`)
|
|
205
|
+
- **Examples**:
|
|
206
|
+
- `'/users'` - Simple path
|
|
207
|
+
- `'/users/$id'` - With parameter
|
|
208
|
+
- `'/users/$id/posts/$postId'` - Multiple parameters
|
|
209
|
+
|
|
210
|
+
#### `responseSchema`
|
|
211
|
+
|
|
212
|
+
- **Type**: `ZodType`
|
|
213
|
+
- **Description**: Zod schema for response validation and type inference
|
|
214
|
+
|
|
215
|
+
#### `requestSchema`
|
|
216
|
+
|
|
217
|
+
- **Type**: `ZodType`
|
|
218
|
+
- **Description**: Zod schema for request body validation (POST/PUT/PATCH)
|
|
219
|
+
|
|
220
|
+
#### `querySchema`
|
|
221
|
+
|
|
222
|
+
- **Type**: `ZodType`
|
|
223
|
+
- **Description**: Zod schema for query parameter validation
|
|
224
|
+
|
|
225
|
+
Use `@navios/builder` instead for better developer experience and type safety.
|
|
226
|
+
|
|
227
|
+
## Endpoint Parameters
|
|
228
|
+
|
|
229
|
+
Endpoint methods receive a single parameter object with the following properties:
|
|
230
|
+
|
|
231
|
+
### `params`
|
|
232
|
+
|
|
233
|
+
URL path parameters extracted from the route:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
// URL: /users/$id
|
|
237
|
+
params: EndpointParams<typeof getUserByIdEndpoint> = {
|
|
238
|
+
params: { id: string },
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// URL: /users/$userId/posts/$postId
|
|
242
|
+
params: EndpointParams<typeof getPostEndpoint> = {
|
|
243
|
+
params: { userId: string, postId: string },
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### `query`
|
|
248
|
+
|
|
249
|
+
Query parameters from the URL:
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
// URL: /users?page=1&search=john
|
|
253
|
+
params: EndpointParams<typeof getUsersEndpoint> = {
|
|
254
|
+
query: { page: number, search: string },
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### `data`
|
|
259
|
+
|
|
260
|
+
Request body for POST/PUT/PATCH requests:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// POST /users with JSON body
|
|
264
|
+
params: EndpointParams<typeof createUserEndpoint> = {
|
|
265
|
+
data: { name: string, email: string },
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Type Safety
|
|
270
|
+
|
|
271
|
+
Navios provides full type safety for endpoints through TypeScript and Zod:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
const UserParamsSchema = z.object({
|
|
275
|
+
id: z.string().uuid(),
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
const UpdateUserSchema = z.object({
|
|
279
|
+
name: z.string().optional(),
|
|
280
|
+
email: z.string().email().optional(),
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
@Controller()
|
|
284
|
+
export class UserController {
|
|
285
|
+
@Endpoint(updateUserEndpoint)
|
|
286
|
+
async updateUser({
|
|
287
|
+
params,
|
|
288
|
+
body,
|
|
289
|
+
}: {
|
|
290
|
+
params: z.infer<typeof UserParamsSchema>
|
|
291
|
+
body: z.infer<typeof UpdateUserSchema>
|
|
292
|
+
}) {
|
|
293
|
+
// params and body are fully typed
|
|
294
|
+
return this.userService.update(params.id, body)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## HTTP Status Codes
|
|
300
|
+
|
|
301
|
+
### Default Status Codes
|
|
302
|
+
|
|
303
|
+
Navios automatically sets appropriate status codes:
|
|
304
|
+
|
|
305
|
+
- `GET` requests: `200 OK`
|
|
306
|
+
- `POST` requests: `201 Created`
|
|
307
|
+
- `PUT`/`PATCH` requests: `200 OK`
|
|
308
|
+
- `DELETE` requests: `204 No Content`
|
|
309
|
+
|
|
310
|
+
### Custom Status Codes
|
|
311
|
+
|
|
312
|
+
Use the `@HttpCode()` decorator to set custom status codes:
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { HttpCode } from '@navios/core'
|
|
316
|
+
|
|
317
|
+
@Controller()
|
|
318
|
+
export class UserController {
|
|
319
|
+
@Endpoint(createUserEndpoint)
|
|
320
|
+
@HttpCode(202) // Accepted
|
|
321
|
+
async verifyUser({ body }: { body: { token: string } }) {
|
|
322
|
+
await this.userService.verify(body.token)
|
|
323
|
+
return { message: 'Verification started' }
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Headers
|
|
329
|
+
|
|
330
|
+
### Reading Headers
|
|
331
|
+
|
|
332
|
+
Access request headers through the headers parameter:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
@Controller()
|
|
336
|
+
export class UserController {
|
|
337
|
+
@Endpoint(getProfileEndpoint)
|
|
338
|
+
async getProfile({ headers }: { headers: Record<string, string> }) {
|
|
339
|
+
const authorization = headers.authorization
|
|
340
|
+
const userId = this.authService.getUserIdFromToken(authorization)
|
|
341
|
+
return this.userService.findById(userId)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Setting Response Headers
|
|
347
|
+
|
|
348
|
+
Use the `@Header()` decorator to set response headers:
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import { Header } from '@navios/core'
|
|
352
|
+
|
|
353
|
+
@Controller()
|
|
354
|
+
export class UserController {
|
|
355
|
+
@Endpoint(usersExportEndpoint)
|
|
356
|
+
@Header('Content-Type', 'text/csv')
|
|
357
|
+
@Header('Content-Disposition', 'attachment; filename="users.csv"')
|
|
358
|
+
async exportUsers() {
|
|
359
|
+
return this.userService.exportToCsv()
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Guards on Endpoints
|
|
365
|
+
|
|
366
|
+
Apply guards to specific endpoints:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { UseGuards } from '@navios/core'
|
|
370
|
+
|
|
371
|
+
@Controller()
|
|
372
|
+
export class UserController {
|
|
373
|
+
@Endpoint(deleteUserEndpoint)
|
|
374
|
+
@UseGuards([AuthGuard, AdminGuard])
|
|
375
|
+
async deleteUser({ params }: { params: { id: string } }) {
|
|
376
|
+
return this.userService.delete(params.id)
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## File Uploads
|
|
382
|
+
|
|
383
|
+
Handle file uploads with multipart support:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
import { Multipart } from '@navios/core'
|
|
387
|
+
|
|
388
|
+
@Controller()
|
|
389
|
+
export class UserController {
|
|
390
|
+
@Multipart(uploadAvatarEndpoint)
|
|
391
|
+
async uploadAvatar({
|
|
392
|
+
params,
|
|
393
|
+
files,
|
|
394
|
+
}: {
|
|
395
|
+
params: { id: string }
|
|
396
|
+
files: { avatar: File }
|
|
397
|
+
}) {
|
|
398
|
+
const avatarUrl = await this.storageService.upload(files.avatar)
|
|
399
|
+
return this.userService.updateAvatar(params.id, avatarUrl)
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Streaming Responses
|
|
405
|
+
|
|
406
|
+
Stream large responses:
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import { Stream } from '@navios/core'
|
|
410
|
+
|
|
411
|
+
@Controller()
|
|
412
|
+
export class UserController {
|
|
413
|
+
@Stream(exportUsersEndpoint)
|
|
414
|
+
async exportUsers() {
|
|
415
|
+
// Return a readable stream
|
|
416
|
+
return this.userService.createExportStream()
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## Error Handling
|
|
422
|
+
|
|
423
|
+
Endpoints can throw HTTP exceptions:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { BadRequestException, NotFoundException } from '@navios/core'
|
|
427
|
+
|
|
428
|
+
@Controller()
|
|
429
|
+
export class UserController {
|
|
430
|
+
@Endpoint(getUserByIdEndpoint)
|
|
431
|
+
async getUserById({ params }: { params: { id: string } }) {
|
|
432
|
+
if (!params.id) {
|
|
433
|
+
throw new BadRequestException('User ID is required')
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const user = await this.userService.findById(params.id)
|
|
437
|
+
if (!user) {
|
|
438
|
+
throw new NotFoundException(`User with ID ${params.id} not found`)
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return user
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
```
|