@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,524 @@
1
+ # Application Setup and Configuration
2
+
3
+ This guide covers how to set up and configure a Navios application, including application creation, module loading, and server configuration.
4
+
5
+ ## Creating a Navios Application
6
+
7
+ ### Basic Application Setup
8
+
9
+ ```typescript
10
+ import { FastifyAdapter } from '@navios/adapter-fastify'
11
+ import { NaviosFactory } from '@navios/core'
12
+
13
+ import { AppModule } from './app.module'
14
+
15
+ async function bootstrap() {
16
+ const app = await NaviosFactory.create(AppModule, {
17
+ adapter: new FastifyAdapter(),
18
+ })
19
+
20
+ await app.listen(3000)
21
+ console.log('Application is running on http://localhost:3000')
22
+ }
23
+
24
+ bootstrap()
25
+ ```
26
+
27
+ ### Application with Multiple Adapters
28
+
29
+ ```typescript
30
+ import { BunAdapter } from '@navios/adapter-bun'
31
+ import { FastifyAdapter } from '@navios/adapter-fastify'
32
+ import { NaviosFactory } from '@navios/core'
33
+
34
+ async function bootstrap() {
35
+ const adapters =
36
+ process.env.NODE_ENV === 'production'
37
+ ? [new FastifyAdapter()]
38
+ : [new BunAdapter(), new FastifyAdapter()]
39
+
40
+ const app = await NaviosFactory.create(AppModule, {
41
+ adapter: adapters,
42
+ })
43
+
44
+ await app.listen(3000)
45
+ }
46
+
47
+ bootstrap()
48
+ ```
49
+
50
+ ## Application Factory
51
+
52
+ The `NaviosFactory` provides methods to create and configure applications:
53
+
54
+ ### `NaviosFactory.create()`
55
+
56
+ ```typescript
57
+ import { NaviosFactory } from '@navios/core'
58
+
59
+ const app = await NaviosFactory.create(AppModule, {
60
+ adapter: new FastifyAdapter(),
61
+ logger: ['error', 'warn', 'log'], // Log levels
62
+ // Additional options
63
+ })
64
+ ```
65
+
66
+ ### Factory Options
67
+
68
+ ```typescript
69
+ interface NaviosApplicationOptions {
70
+ adapter: NaviosEnvironmentOptions | NaviosEnvironmentOptions[]
71
+ logger?: LoggerService | LogLevel[] | false
72
+ }
73
+ ```
74
+
75
+ ## Application Module
76
+
77
+ The root application module serves as the entry point:
78
+
79
+ ```typescript
80
+ import { Module } from '@navios/core'
81
+
82
+ import { AuthModule } from './auth/auth.module'
83
+ import { DatabaseModule } from './database/database.module'
84
+ import { UserModule } from './user/user.module'
85
+
86
+ @Module({
87
+ imports: [DatabaseModule, AuthModule, UserModule],
88
+ })
89
+ export class AppModule {}
90
+ ```
91
+
92
+ ## Application Lifecycle
93
+
94
+ ### Application Initialization
95
+
96
+ ```typescript
97
+ async function bootstrap() {
98
+ // 1. Create application
99
+ const app = await NaviosFactory.create(AppModule, {
100
+ adapter: new FastifyAdapter(),
101
+ })
102
+
103
+ // 2. Configure middleware, CORS, etc.
104
+ app.enableCors({
105
+ origin: process.env.ALLOWED_ORIGINS?.split(',') || [
106
+ 'http://localhost:3000',
107
+ ],
108
+ })
109
+
110
+ app.enableMultipart({
111
+ limits: {
112
+ fileSize: 10_000_000, // 10MB
113
+ },
114
+ })
115
+
116
+ // 3. Start listening
117
+ await app.listen(3000)
118
+ }
119
+ ```
120
+
121
+ ### Graceful Shutdown
122
+
123
+ ```typescript
124
+ async function bootstrap() {
125
+ const app = await NaviosFactory.create(AppModule, {
126
+ adapter: new FastifyAdapter(),
127
+ })
128
+
129
+ await app.listen(3000)
130
+
131
+ // Handle graceful shutdown
132
+ process.on('SIGTERM', async () => {
133
+ console.log('SIGTERM received, shutting down gracefully...')
134
+ await app.close()
135
+ process.exit(0)
136
+ })
137
+
138
+ process.on('SIGINT', async () => {
139
+ console.log('SIGINT received, shutting down gracefully...')
140
+ await app.close()
141
+ process.exit(0)
142
+ })
143
+ }
144
+ ```
145
+
146
+ ## Environment Configuration
147
+
148
+ ### Environment Variables
149
+
150
+ ```typescript
151
+ // config/environment.ts
152
+ export const environment = {
153
+ port: parseInt(process.env.PORT || '3000', 10),
154
+ nodeEnv: process.env.NODE_ENV || 'development',
155
+ database: {
156
+ url: process.env.DATABASE_URL || 'postgresql://localhost:5432/navios',
157
+ maxConnections: parseInt(process.env.DB_MAX_CONNECTIONS || '10', 10),
158
+ },
159
+ jwt: {
160
+ secret: process.env.JWT_SECRET || 'super-secret',
161
+ expiresIn: process.env.JWT_EXPIRES_IN || '1h',
162
+ },
163
+ cors: {
164
+ origin: process.env.CORS_ORIGIN?.split(',') || ['http://localhost:3000'],
165
+ },
166
+ }
167
+ ```
168
+
169
+ ### Configuration Service
170
+
171
+ ```typescript
172
+ import { Injectable } from '@navios/core'
173
+
174
+ @Injectable()
175
+ export class ConfigService {
176
+ private config = new Map()
177
+
178
+ constructor() {
179
+ this.loadEnvironmentVariables()
180
+ }
181
+
182
+ get<T>(key: string): T {
183
+ return this.config.get(key)
184
+ }
185
+
186
+ private loadEnvironmentVariables() {
187
+ this.config.set('PORT', parseInt(process.env.PORT || '3000', 10))
188
+ this.config.set('NODE_ENV', process.env.NODE_ENV || 'development')
189
+ this.config.set('DATABASE_URL', process.env.DATABASE_URL)
190
+ this.config.set('JWT_SECRET', process.env.JWT_SECRET)
191
+ // ... more configuration
192
+ }
193
+ }
194
+
195
+ // Usage in bootstrap
196
+ async function bootstrap() {
197
+ const app = await NaviosFactory.create(AppModule, {
198
+ adapter: new FastifyAdapter(),
199
+ })
200
+
201
+ const configService = app.getContainer().get(ConfigService)
202
+ const port = configService.get<number>('PORT')
203
+
204
+ await app.listen(port)
205
+ }
206
+ ```
207
+
208
+ ## CORS Configuration
209
+
210
+ Enable Cross-Origin Resource Sharing:
211
+
212
+ ```typescript
213
+ async function bootstrap() {
214
+ const app = await NaviosFactory.create(AppModule, {
215
+ adapter: new FastifyAdapter(),
216
+ })
217
+
218
+ // Basic CORS
219
+ app.enableCors()
220
+
221
+ // Advanced CORS configuration
222
+ app.enableCors({
223
+ origin: ['http://localhost:3000', 'https://yourdomain.com'],
224
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
225
+ allowedHeaders: ['Content-Type', 'Authorization'],
226
+ credentials: true,
227
+ })
228
+
229
+ await app.listen(3000)
230
+ }
231
+ ```
232
+
233
+ ## Multipart/File Upload Configuration
234
+
235
+ Enable file upload support:
236
+
237
+ ```typescript
238
+ async function bootstrap() {
239
+ const app = await NaviosFactory.create(AppModule, {
240
+ adapter: new FastifyAdapter(),
241
+ })
242
+
243
+ app.enableMultipart({
244
+ limits: {
245
+ fieldNameSize: 100, // Max field name size in bytes
246
+ fieldSize: 100, // Max field value size in bytes
247
+ fields: 10, // Max number of non-file fields
248
+ fileSize: 10_000_000, // Max file size in bytes (10MB)
249
+ files: 5, // Max number of file fields
250
+ headerPairs: 2000, // Max number of header key=>value pairs
251
+ },
252
+ })
253
+
254
+ await app.listen(3000)
255
+ }
256
+ ```
257
+
258
+ ## Logging Configuration
259
+
260
+ ### Custom Logger
261
+
262
+ ```typescript
263
+ import { LoggerService, LogLevel } from '@navios/core'
264
+
265
+ class CustomLogger implements LoggerService {
266
+ log(message: string, context?: string) {
267
+ console.log(`[${context}] ${message}`)
268
+ }
269
+
270
+ error(message: string, trace?: string, context?: string) {
271
+ console.error(`[${context}] ERROR: ${message}`, trace)
272
+ }
273
+
274
+ warn(message: string, context?: string) {
275
+ console.warn(`[${context}] WARN: ${message}`)
276
+ }
277
+
278
+ debug(message: string, context?: string) {
279
+ if (process.env.DEBUG) {
280
+ console.debug(`[${context}] DEBUG: ${message}`)
281
+ }
282
+ }
283
+
284
+ verbose(message: string, context?: string) {
285
+ if (process.env.VERBOSE) {
286
+ console.log(`[${context}] VERBOSE: ${message}`)
287
+ }
288
+ }
289
+ }
290
+
291
+ // Use custom logger
292
+ const app = await NaviosFactory.create(AppModule, {
293
+ adapter: new FastifyAdapter(),
294
+ logger: new CustomLogger(),
295
+ })
296
+ ```
297
+
298
+ ### Log Levels
299
+
300
+ ```typescript
301
+ const app = await NaviosFactory.create(AppModule, {
302
+ adapter: new FastifyAdapter(),
303
+ logger: ['error', 'warn', 'log'], // Only these levels will be logged
304
+ })
305
+
306
+ // Or disable logging
307
+ const app = await NaviosFactory.create(AppModule, {
308
+ adapter: new FastifyAdapter(),
309
+ logger: false,
310
+ })
311
+ ```
312
+
313
+ ## Database Integration
314
+
315
+ ### Database Module
316
+
317
+ ```typescript
318
+ import { Injectable, Module } from '@navios/core'
319
+
320
+ import { PrismaClient } from '@prisma/client'
321
+
322
+ @Injectable()
323
+ export class DatabaseService extends PrismaClient {
324
+ constructor() {
325
+ super({
326
+ datasources: {
327
+ db: {
328
+ url: process.env.DATABASE_URL,
329
+ },
330
+ },
331
+ })
332
+ }
333
+
334
+ async onModuleInit() {
335
+ await this.$connect()
336
+ }
337
+
338
+ async onModuleDestroy() {
339
+ await this.$disconnect()
340
+ }
341
+ }
342
+
343
+ @Module({
344
+ providers: [DatabaseService],
345
+ exports: [DatabaseService],
346
+ })
347
+ export class DatabaseModule {}
348
+ ```
349
+
350
+ ## Health Checks
351
+
352
+ Add health check endpoints using `@navios/builder`:
353
+
354
+ ```typescript
355
+ // api/health.ts
356
+ import { builder } from '@navios/builder'
357
+
358
+ import { z } from 'zod'
359
+
360
+ export const api = builder()
361
+
362
+ export const healthEndpoint = api.declareEndpoint({
363
+ method: 'GET',
364
+ url: '/health',
365
+ responseSchema: z.object({
366
+ status: z.string(),
367
+ timestamp: z.string(),
368
+ uptime: z.number(),
369
+ }),
370
+ })
371
+
372
+ export const readinessEndpoint = api.declareEndpoint({
373
+ method: 'GET',
374
+ url: '/health/ready',
375
+ responseSchema: z.object({
376
+ ready: z.boolean(),
377
+ checks: z.record(z.string(), z.boolean()),
378
+ }),
379
+ })
380
+ ```
381
+
382
+ ```typescript
383
+ import type { EndpointParams } from '@navios/core'
384
+
385
+ import { Controller, Endpoint } from '@navios/core'
386
+
387
+ import { healthEndpoint, readinessEndpoint } from '../api/health.js'
388
+
389
+ // controllers/health.controller.ts
390
+
391
+ @Controller()
392
+ export class HealthController {
393
+ @Endpoint(healthEndpoint)
394
+ async getHealth(params: EndpointParams<typeof healthEndpoint>) {
395
+ return {
396
+ status: 'ok',
397
+ timestamp: new Date().toISOString(),
398
+ uptime: process.uptime(),
399
+ }
400
+ }
401
+
402
+ @Endpoint(readinessEndpoint)
403
+ async getReadiness(params: EndpointParams<typeof readinessEndpoint>) {
404
+ // Check database connectivity, external services, etc.
405
+ try {
406
+ await this.databaseService.isConnected()
407
+ return { status: 'ready' }
408
+ } catch (error) {
409
+ throw new InternalServerErrorException('Service not ready')
410
+ }
411
+ }
412
+ }
413
+ ```
414
+
415
+ ## Production Configuration
416
+
417
+ ### Production Bootstrap
418
+
419
+ ```typescript
420
+ import { defineFastifyEnvironment } from '@navios/adapter-fastify'
421
+ import { NaviosFactory } from '@navios/core'
422
+
423
+ import { AppModule } from './app.module'
424
+
425
+ async function bootstrap() {
426
+ const app = await NaviosFactory.create(AppModule, {
427
+ adapter: defineFastifyEnvironment({
428
+ logger: process.env.NODE_ENV === 'production',
429
+ trustProxy: true,
430
+ }),
431
+ logger:
432
+ process.env.NODE_ENV === 'production'
433
+ ? ['error', 'warn', 'log']
434
+ : ['error', 'warn', 'log', 'debug', 'verbose'],
435
+ })
436
+
437
+ // Production middleware
438
+ if (process.env.NODE_ENV === 'production') {
439
+ app.enableCors({
440
+ origin: process.env.ALLOWED_ORIGINS?.split(','),
441
+ credentials: true,
442
+ })
443
+ } else {
444
+ app.enableCors() // Allow all origins in development
445
+ }
446
+
447
+ const port = process.env.PORT || 3000
448
+ await app.listen({
449
+ port: parseInt(port, 10),
450
+ host: '0.0.0.0',
451
+ })
452
+
453
+ console.log(`🚀 Application is running on port ${port}`)
454
+ }
455
+
456
+ bootstrap().catch((error) => {
457
+ console.error('Failed to start application:', error)
458
+ process.exit(1)
459
+ })
460
+ ```
461
+
462
+ ### Docker Configuration
463
+
464
+ ```dockerfile
465
+ FROM node:18-alpine
466
+
467
+ WORKDIR /app
468
+
469
+ COPY package*.json ./
470
+ RUN npm ci --only=production
471
+
472
+ COPY . .
473
+ RUN npm run build
474
+
475
+ EXPOSE 3000
476
+
477
+ USER node
478
+
479
+ CMD ["node", "dist/main.js"]
480
+ ```
481
+
482
+ ### Environment Variables for Production
483
+
484
+ ```bash
485
+ # .env.production
486
+ NODE_ENV=production
487
+ PORT=3000
488
+ DATABASE_URL=postgresql://user:password@db:5432/navios_prod
489
+ LOG_LEVEL=error,warn,log
490
+ ```
491
+
492
+ ## Testing Configuration
493
+
494
+ ### Test Application Setup
495
+
496
+ ```typescript
497
+ import { Test } from '@navios/testing'
498
+
499
+ import { AppModule } from '../src/app.module'
500
+
501
+ describe('Application', () => {
502
+ let app: any
503
+
504
+ beforeAll(async () => {
505
+ const moduleRef = await Test.createTestingModule({
506
+ imports: [AppModule],
507
+ })
508
+ .overrideProvider(DatabaseService)
509
+ .useValue(mockDatabaseService)
510
+ .compile()
511
+
512
+ app = moduleRef.createNaviosApplication()
513
+ await app.init()
514
+ })
515
+
516
+ afterAll(async () => {
517
+ await app.close()
518
+ })
519
+
520
+ it('should be defined', () => {
521
+ expect(app).toBeDefined()
522
+ })
523
+ })
524
+ ```