@navios/core 0.4.0 → 0.5.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.
Files changed (92) hide show
  1. package/README.md +95 -2
  2. package/docs/README.md +310 -3
  3. package/docs/adapters.md +308 -0
  4. package/docs/application-setup.md +524 -0
  5. package/docs/attributes.md +689 -0
  6. package/docs/controllers.md +373 -0
  7. package/docs/endpoints.md +444 -0
  8. package/docs/exceptions.md +316 -0
  9. package/docs/guards.md +550 -0
  10. package/docs/modules.md +251 -0
  11. package/docs/quick-start.md +295 -0
  12. package/docs/services.md +428 -0
  13. package/docs/testing.md +704 -0
  14. package/lib/_tsup-dts-rollup.d.mts +300 -235
  15. package/lib/_tsup-dts-rollup.d.ts +300 -235
  16. package/lib/index.d.mts +47 -26
  17. package/lib/index.d.ts +47 -26
  18. package/lib/index.js +633 -1072
  19. package/lib/index.js.map +1 -1
  20. package/lib/index.mjs +631 -1064
  21. package/lib/index.mjs.map +1 -1
  22. package/package.json +4 -7
  23. package/project.json +9 -1
  24. package/src/__tests__/config.service.spec.mts +11 -9
  25. package/src/__tests__/controller.spec.mts +0 -1
  26. package/src/config/config.service.mts +2 -2
  27. package/src/decorators/controller.decorator.mts +1 -1
  28. package/src/decorators/endpoint.decorator.mts +2 -2
  29. package/src/decorators/header.decorator.mts +1 -1
  30. package/src/decorators/multipart.decorator.mts +1 -1
  31. package/src/decorators/stream.decorator.mts +2 -3
  32. package/src/factories/endpoint-adapter.factory.mts +21 -0
  33. package/src/factories/http-adapter.factory.mts +20 -0
  34. package/src/factories/index.mts +6 -0
  35. package/src/factories/multipart-adapter.factory.mts +21 -0
  36. package/src/factories/reply.factory.mts +21 -0
  37. package/src/factories/request.factory.mts +21 -0
  38. package/src/factories/stream-adapter.factory.mts +20 -0
  39. package/src/index.mts +1 -1
  40. package/src/interfaces/abstract-execution-context.inteface.mts +13 -0
  41. package/src/interfaces/abstract-http-adapter.interface.mts +20 -0
  42. package/src/interfaces/abstract-http-cors-options.interface.mts +59 -0
  43. package/src/interfaces/abstract-http-handler-adapter.interface.mts +13 -0
  44. package/src/interfaces/abstract-http-listen-options.interface.mts +4 -0
  45. package/src/interfaces/can-activate.mts +4 -2
  46. package/src/interfaces/http-header.mts +18 -0
  47. package/src/interfaces/index.mts +6 -0
  48. package/src/logger/console-logger.service.mts +28 -44
  49. package/src/logger/index.mts +1 -2
  50. package/src/logger/logger.service.mts +9 -128
  51. package/src/logger/logger.tokens.mts +21 -0
  52. package/src/metadata/handler.metadata.mts +7 -5
  53. package/src/navios.application.mts +65 -172
  54. package/src/navios.environment.mts +30 -0
  55. package/src/navios.factory.mts +53 -12
  56. package/src/services/guard-runner.service.mts +19 -9
  57. package/src/services/index.mts +0 -2
  58. package/src/services/module-loader.service.mts +4 -3
  59. package/src/tokens/endpoint-adapter.token.mts +8 -0
  60. package/src/tokens/execution-context.token.mts +2 -2
  61. package/src/tokens/http-adapter.token.mts +8 -0
  62. package/src/tokens/index.mts +4 -1
  63. package/src/tokens/multipart-adapter.token.mts +8 -0
  64. package/src/tokens/reply.token.mts +1 -5
  65. package/src/tokens/request.token.mts +1 -7
  66. package/src/tokens/stream-adapter.token.mts +8 -0
  67. package/docs/recipes/prisma.md +0 -60
  68. package/e2e/endpoints/get.spec.mts +0 -97
  69. package/e2e/endpoints/post.spec.mts +0 -113
  70. package/examples/simple-test/api/index.mts +0 -64
  71. package/examples/simple-test/config/config.service.mts +0 -14
  72. package/examples/simple-test/config/configuration.mts +0 -7
  73. package/examples/simple-test/index.mts +0 -16
  74. package/examples/simple-test/src/acl/acl-modern.guard.mts +0 -15
  75. package/examples/simple-test/src/acl/acl.guard.mts +0 -14
  76. package/examples/simple-test/src/acl/app.guard.mts +0 -27
  77. package/examples/simple-test/src/acl/one-more.guard.mts +0 -15
  78. package/examples/simple-test/src/acl/public.attribute.mts +0 -21
  79. package/examples/simple-test/src/app.module.mts +0 -9
  80. package/examples/simple-test/src/user/user.controller.mts +0 -72
  81. package/examples/simple-test/src/user/user.module.mts +0 -14
  82. package/examples/simple-test/src/user/user.service.mts +0 -14
  83. package/src/adapters/endpoint-adapter.service.mts +0 -72
  84. package/src/adapters/handler-adapter.interface.mts +0 -21
  85. package/src/adapters/index.mts +0 -4
  86. package/src/adapters/multipart-adapter.service.mts +0 -135
  87. package/src/adapters/stream-adapter.service.mts +0 -91
  88. package/src/logger/logger.factory.mts +0 -36
  89. package/src/logger/pino-wrapper.mts +0 -64
  90. package/src/services/controller-adapter.service.mts +0 -124
  91. package/src/services/execution-context.mts +0 -54
  92. 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
+ ```