@stefaninigo/core 0.9.0 → 1.0.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 (107) hide show
  1. package/README.md +339 -51
  2. package/dist/libs/stefaninigo/cache/local/loca.service.d.ts +2 -0
  3. package/dist/libs/stefaninigo/cache/local/loca.service.js +30 -1
  4. package/dist/libs/stefaninigo/cache/local/loca.service.js.map +1 -1
  5. package/dist/libs/stefaninigo/core/bootstrap/bootstrap.helpers.d.ts +16 -2
  6. package/dist/libs/stefaninigo/core/bootstrap/bootstrap.helpers.js +47 -7
  7. package/dist/libs/stefaninigo/core/bootstrap/bootstrap.helpers.js.map +1 -1
  8. package/dist/libs/stefaninigo/core/config/env.utils.d.ts +3 -0
  9. package/dist/libs/stefaninigo/core/config/env.utils.js +28 -0
  10. package/dist/libs/stefaninigo/core/config/env.utils.js.map +1 -0
  11. package/dist/libs/stefaninigo/core/config/index.d.ts +1 -0
  12. package/dist/libs/stefaninigo/core/config/index.js +18 -0
  13. package/dist/libs/stefaninigo/core/config/index.js.map +1 -0
  14. package/dist/libs/stefaninigo/core/context/index.d.ts +2 -0
  15. package/dist/libs/stefaninigo/core/context/index.js +19 -0
  16. package/dist/libs/stefaninigo/core/context/index.js.map +1 -0
  17. package/dist/libs/stefaninigo/core/context/request-context.d.ts +11 -0
  18. package/dist/libs/stefaninigo/core/context/request-context.js +14 -0
  19. package/dist/libs/stefaninigo/core/context/request-context.js.map +1 -0
  20. package/dist/libs/stefaninigo/core/context/request-context.middleware.d.ts +5 -0
  21. package/dist/libs/stefaninigo/core/context/request-context.middleware.js +27 -0
  22. package/dist/libs/stefaninigo/core/context/request-context.middleware.js.map +1 -0
  23. package/dist/libs/stefaninigo/core/dtos/index.d.ts +1 -0
  24. package/dist/libs/stefaninigo/core/dtos/index.js +1 -0
  25. package/dist/libs/stefaninigo/core/dtos/index.js.map +1 -1
  26. package/dist/libs/stefaninigo/core/dtos/paginated-result.dto.d.ts +11 -0
  27. package/dist/libs/stefaninigo/core/dtos/paginated-result.dto.js +56 -0
  28. package/dist/libs/stefaninigo/core/dtos/paginated-result.dto.js.map +1 -0
  29. package/dist/libs/stefaninigo/core/dtos/problem-details.dto.d.ts +1 -0
  30. package/dist/libs/stefaninigo/core/dtos/problem-details.dto.js +8 -0
  31. package/dist/libs/stefaninigo/core/dtos/problem-details.dto.js.map +1 -1
  32. package/dist/libs/stefaninigo/core/filters/http-exception.filter.d.ts +12 -0
  33. package/dist/libs/stefaninigo/core/filters/http-exception.filter.js +145 -0
  34. package/dist/libs/stefaninigo/core/filters/http-exception.filter.js.map +1 -0
  35. package/dist/libs/stefaninigo/core/filters/index.d.ts +1 -0
  36. package/dist/libs/stefaninigo/core/filters/index.js +18 -0
  37. package/dist/libs/stefaninigo/core/filters/index.js.map +1 -0
  38. package/dist/libs/stefaninigo/core/health/health.module.js +2 -1
  39. package/dist/libs/stefaninigo/core/health/health.module.js.map +1 -1
  40. package/dist/libs/stefaninigo/core/health/health.types.d.ts +1 -0
  41. package/dist/libs/stefaninigo/core/health/health.types.js.map +1 -1
  42. package/dist/libs/stefaninigo/core/index.d.ts +4 -0
  43. package/dist/libs/stefaninigo/core/index.js +4 -0
  44. package/dist/libs/stefaninigo/core/index.js.map +1 -1
  45. package/dist/libs/stefaninigo/core/interceptors/logging.interceptor.js +15 -10
  46. package/dist/libs/stefaninigo/core/interceptors/logging.interceptor.js.map +1 -1
  47. package/dist/libs/stefaninigo/core/interceptors/problem-details.interceptor.js +22 -13
  48. package/dist/libs/stefaninigo/core/interceptors/problem-details.interceptor.js.map +1 -1
  49. package/dist/libs/stefaninigo/core/interceptors/response.interceptor.js +2 -2
  50. package/dist/libs/stefaninigo/core/interceptors/response.interceptor.js.map +1 -1
  51. package/dist/libs/stefaninigo/core/logger/index.d.ts +1 -0
  52. package/dist/libs/stefaninigo/core/logger/index.js +18 -0
  53. package/dist/libs/stefaninigo/core/logger/index.js.map +1 -0
  54. package/dist/libs/stefaninigo/core/logger/traced-logger.d.ts +7 -0
  55. package/dist/libs/stefaninigo/core/logger/traced-logger.js +21 -0
  56. package/dist/libs/stefaninigo/core/logger/traced-logger.js.map +1 -0
  57. package/dist/libs/stefaninigo/database/database-service.interface.d.ts +1 -4
  58. package/dist/libs/stefaninigo/database/dynamodb/dynamodb.service.d.ts +2 -2
  59. package/dist/libs/stefaninigo/database/dynamodb/dynamodb.service.js +1 -4
  60. package/dist/libs/stefaninigo/database/dynamodb/dynamodb.service.js.map +1 -1
  61. package/dist/libs/stefaninigo/database/mongodb/mongodb.service.d.ts +5 -3
  62. package/dist/libs/stefaninigo/database/mongodb/mongodb.service.js +43 -21
  63. package/dist/libs/stefaninigo/database/mongodb/mongodb.service.js.map +1 -1
  64. package/dist/libs/stefaninigo/database/postgresdb/postgresdb.services.d.ts +3 -3
  65. package/dist/libs/stefaninigo/database/postgresdb/postgresdb.services.js +39 -27
  66. package/dist/libs/stefaninigo/database/postgresdb/postgresdb.services.js.map +1 -1
  67. package/dist/libs/stefaninigo/database/utils/index.d.ts +1 -0
  68. package/dist/libs/stefaninigo/database/utils/index.js +18 -0
  69. package/dist/libs/stefaninigo/database/utils/index.js.map +1 -0
  70. package/dist/libs/stefaninigo/database/utils/normalize-list.d.ts +6 -0
  71. package/dist/libs/stefaninigo/database/utils/normalize-list.js +13 -0
  72. package/dist/libs/stefaninigo/database/utils/normalize-list.js.map +1 -0
  73. package/dist/libs/stefaninigo/events/event-bus/event-bus.module.d.ts +2 -0
  74. package/dist/libs/stefaninigo/events/event-bus/event-bus.module.js +22 -0
  75. package/dist/libs/stefaninigo/events/event-bus/event-bus.module.js.map +1 -0
  76. package/dist/libs/stefaninigo/events/event-bus/event-bus.service.d.ts +21 -0
  77. package/dist/libs/stefaninigo/events/event-bus/event-bus.service.js +130 -0
  78. package/dist/libs/stefaninigo/events/event-bus/event-bus.service.js.map +1 -0
  79. package/dist/libs/stefaninigo/events/event-bus/event-bus.types.d.ts +13 -0
  80. package/dist/libs/stefaninigo/events/event-bus/event-bus.types.js +3 -0
  81. package/dist/libs/stefaninigo/events/event-bus/event-bus.types.js.map +1 -0
  82. package/dist/libs/stefaninigo/events/event-bus/index.d.ts +3 -0
  83. package/dist/libs/stefaninigo/events/event-bus/index.js +20 -0
  84. package/dist/libs/stefaninigo/events/event-bus/index.js.map +1 -0
  85. package/dist/libs/stefaninigo/events/index.d.ts +1 -0
  86. package/dist/libs/stefaninigo/events/index.js +1 -0
  87. package/dist/libs/stefaninigo/events/index.js.map +1 -1
  88. package/dist/libs/stefaninigo/events/types/domain-events.d.ts +3 -145
  89. package/dist/libs/stefaninigo/index.d.ts +2 -2
  90. package/dist/libs/stefaninigo/index.js +2 -2
  91. package/dist/libs/stefaninigo/index.js.map +1 -1
  92. package/dist/libs/stefaninigo/messaging/sns/sns.service.d.ts +1 -3
  93. package/dist/libs/stefaninigo/messaging/sns/sns.service.js +1 -25
  94. package/dist/libs/stefaninigo/messaging/sns/sns.service.js.map +1 -1
  95. package/dist/libs/stefaninigo/messaging/sqs/sqs.service.d.ts +2 -1
  96. package/dist/libs/stefaninigo/messaging/sqs/sqs.service.js +9 -1
  97. package/dist/libs/stefaninigo/messaging/sqs/sqs.service.js.map +1 -1
  98. package/dist/libs/stefaninigo/storage/s3/s3-services.d.ts +2 -0
  99. package/dist/libs/stefaninigo/storage/s3/s3-services.js +35 -7
  100. package/dist/libs/stefaninigo/storage/s3/s3-services.js.map +1 -1
  101. package/dist/libs/stefaninigo/storage/storage.interface.d.ts +1 -0
  102. package/dist/libs/stefaninigo/transport/trasnport.module.d.ts +6 -1
  103. package/dist/libs/stefaninigo/transport/trasnport.module.js +7 -11
  104. package/dist/libs/stefaninigo/transport/trasnport.module.js.map +1 -1
  105. package/dist/libs/stefaninigo/transport/web-socket/aws/aws-ws-transport.service.js +0 -4
  106. package/dist/libs/stefaninigo/transport/web-socket/aws/aws-ws-transport.service.js.map +1 -1
  107. package/package.json +2 -2
package/README.md CHANGED
@@ -1,73 +1,361 @@
1
- <p align="center">
2
- <a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
3
- </p>
4
-
5
- [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6
- [circleci-url]: https://circleci.com/gh/nestjs/nest
7
-
8
- <p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
9
- <p align="center">
10
- <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
11
- <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
12
- <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
13
- <a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
14
- <a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
15
- <a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
16
- <a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
17
- <a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
18
- <a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
19
- <a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
20
- <a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
21
- </p>
22
- <!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
23
- [![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
24
-
25
- ## Description
26
-
27
- [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
1
+ # stefaninigo
2
+
3
+ Enterprise-grade NestJS library for the StefaniniGo microservice ecosystem. Provides database access, file storage, caching, messaging, real-time transport, event-driven architecture, geolocation utilities, health checks, and standardized request/response handling -- all through a unified **Strategy + DynamicModule** pattern.
4
+
5
+ ## Design Philosophy
6
+
7
+ - **Transversal** -- shared foundation for all microservices in the ecosystem.
8
+ - **Generic** -- no business logic; only infrastructure concerns.
9
+ - **Provider-agnostic** -- every infrastructure module defines a **service interface**; concrete implementations (strategies) are swappable without touching consumer code.
10
+ - **Easy integration** -- `forRootAsync()` one-liner registration, `@Inject('token')` consumption.
28
11
 
29
12
  ## Installation
30
13
 
31
14
  ```bash
32
- $ pnpm install
15
+ npm install stefaninigo
33
16
  ```
34
17
 
35
- ## Running the app
18
+ ## Quick Start
36
19
 
37
- ```bash
38
- # development
39
- $ pnpm run start
20
+ ```typescript
21
+ // app.module.ts
22
+ import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
23
+ import { ConfigModule } from '@nestjs/config';
24
+ import {
25
+ DatabaseModule,
26
+ StorageModule,
27
+ CacheModule,
28
+ EventBusModule,
29
+ HealthModule,
30
+ TraceIdMiddleware,
31
+ RequestContextMiddleware,
32
+ LoggingInterceptor,
33
+ ResponseInterceptor,
34
+ ProblemDetailsInterceptor,
35
+ } from 'stefaninigo';
36
+ import { APP_INTERCEPTOR } from '@nestjs/core';
37
+ import configuration from './config/configuration';
38
+
39
+ @Module({
40
+ imports: [
41
+ ConfigModule.forRoot({ load: [configuration], isGlobal: true }),
40
42
 
41
- # watch mode
42
- $ pnpm run start:dev
43
+ // Database -- MongoDB provider with injection token 'db'
44
+ DatabaseModule.forRootAsync([
45
+ { name: 'db', provider: DatabaseModule.PROVIDERS.MONGODB },
46
+ ]),
43
47
 
44
- # production mode
45
- $ pnpm run start:prod
48
+ // Storage -- S3 provider with injection token 'storage'
49
+ StorageModule.forRootAsync([
50
+ { name: 'storage', provider: StorageModule.PROVIDERS.S3 },
51
+ ]),
52
+
53
+ // Cache -- Redis provider with injection token 'cache'
54
+ CacheModule.forRootAsync([
55
+ { name: 'cache', provider: CacheModule.PROVIDERS.REDIS },
56
+ ]),
57
+
58
+ // Event bus -- global module, no forRoot needed
59
+ EventBusModule,
60
+
61
+ // Health checks
62
+ HealthModule.forRoot({
63
+ config: {
64
+ serviceName: 'my-service',
65
+ version: '1.0.0',
66
+ database: {
67
+ token: 'db',
68
+ collection: 'health',
69
+ timeoutMs: 3000,
70
+ },
71
+ },
72
+ }),
73
+ ],
74
+ providers: [
75
+ // Interceptor chain (order matters -- first registered runs outermost)
76
+ { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor },
77
+ { provide: APP_INTERCEPTOR, useClass: ResponseInterceptor },
78
+ { provide: APP_INTERCEPTOR, useClass: ProblemDetailsInterceptor },
79
+ ],
80
+ })
81
+ export class AppModule implements NestModule {
82
+ configure(consumer: MiddlewareConsumer) {
83
+ consumer
84
+ .apply(TraceIdMiddleware, RequestContextMiddleware)
85
+ .forRoutes('*');
86
+ }
87
+ }
46
88
  ```
47
89
 
48
- ## Test
90
+ ```typescript
91
+ // main.ts
92
+ import { NestFactory } from '@nestjs/core';
93
+ import { AppModule } from './app.module';
94
+ import {
95
+ createStandardValidationPipe,
96
+ setupSwagger,
97
+ setupCors,
98
+ } from 'stefaninigo';
49
99
 
50
- ```bash
51
- # unit tests
52
- $ pnpm run test
100
+ async function bootstrap() {
101
+ const app = await NestFactory.create(AppModule);
53
102
 
54
- # e2e tests
55
- $ pnpm run test:e2e
103
+ app.useGlobalPipes(createStandardValidationPipe());
104
+ app.setGlobalPrefix('api/v1/my-service');
105
+ setupCors(app);
106
+ setupSwagger(app, {
107
+ title: 'My Service',
108
+ description: 'API docs',
109
+ version: '1.0.0',
110
+ });
56
111
 
57
- # test coverage
58
- $ pnpm run test:cov
112
+ await app.listen(3000);
113
+ }
114
+ bootstrap();
59
115
  ```
60
116
 
61
- ## Support
117
+ ## Modules
118
+
119
+ | Module | Pattern | Providers | Description |
120
+ |--------|---------|-----------|-------------|
121
+ | [`DatabaseModule`](libs/stefaninigo/src/database/ARCHITECTURE.md) | Strategy + DynamicModule | MongoDB, DynamoDB, PostgreSQL | Provider-agnostic data access layer |
122
+ | [`StorageModule`](libs/stefaninigo/src/storage/ARCHITECTURE.md) | Strategy + DynamicModule | S3 | File upload, download, presigned URLs |
123
+ | [`CacheModule`](libs/stefaninigo/src/cache/ARCHITECTURE.md) | Strategy + DynamicModule | Redis, Local (in-memory) | Key-value caching with TTL |
124
+ | [`MessagingModule`](libs/stefaninigo/src/messaging/ARCHITECTURE.md) | Strategy + DynamicModule | SNS, SQS | Pub/sub and point-to-point messaging |
125
+ | [`TransportModule`](libs/stefaninigo/src/transport/ARCHITECTURE.md) | Strategy + DynamicModule | AWS API Gateway WebSocket | Real-time bidirectional communication |
126
+ | [`EventBusModule`](libs/stefaninigo/src/events/ARCHITECTURE.md) | `@Global` module | log, SNS, SQS | Toggleable domain event publishing |
127
+ | [`HealthModule`](libs/stefaninigo/src/core/ARCHITECTURE.md) | DynamicModule | -- | K8s liveness, readiness, detailed health |
128
+ | [Core](libs/stefaninigo/src/core/ARCHITECTURE.md) | Interceptors + Middleware | -- | Tracing, logging, RFC 7807 errors, response format |
129
+ | [Config](libs/stefaninigo/src/config/ARCHITECTURE.md) | Service | -- | Centralized config resolver for all modules |
130
+ | [Geo](libs/stefaninigo/src/geo/ARCHITECTURE.md) | Pure utilities | -- | GeoJSON types, Haversine distance, bounding boxes |
131
+
132
+ ## Architecture
133
+
134
+ ### Strategy Pattern
135
+
136
+ Every infrastructure module (`DatabaseModule`, `StorageModule`, `CacheModule`, `MessagingModule`, `TransportModule`) follows the same pattern:
137
+
138
+ 1. A **service interface** defines the contract (e.g. `DatabaseService`, `StorageService`, `CacheServiceInterface`).
139
+ 2. **Concrete strategies** implement that interface per provider (e.g. `MongoDBService`, `DynamoDBService`, `PostgreService`).
140
+ 3. The module exposes `forRootAsync(providers[])` which takes an array of `{ name, provider }` configs.
141
+ 4. Each entry creates a named NestJS provider you inject with `@Inject('name')`.
142
+
143
+ ```typescript
144
+ // Register two databases with different tokens
145
+ DatabaseModule.forRootAsync([
146
+ { name: 'mainDb', provider: DatabaseModule.PROVIDERS.MONGODB },
147
+ { name: 'analyticsDb', provider: DatabaseModule.PROVIDERS.MONGODB, configKey: 'analytics' },
148
+ { name: 'dynamoDb', provider: DatabaseModule.PROVIDERS.DYNAMODB },
149
+ ])
150
+
151
+ // Inject in a service
152
+ constructor(@Inject('mainDb') private readonly db: DatabaseService) {}
153
+ ```
154
+
155
+ ### Interceptor Chain
156
+
157
+ Interceptors execute in registration order on the request path and in reverse on the response/error path:
158
+
159
+ ```
160
+ Request Flow:
161
+ Client --> LoggingInterceptor --> ResponseInterceptor --> ProblemDetailsInterceptor --> Controller
162
+
163
+ Response Flow (success):
164
+ Controller --> ProblemDetailsInterceptor (pass-through) --> ResponseInterceptor (wraps: {success, message}) --> LoggingInterceptor (logs duration) --> Client
165
+
166
+ Error Flow:
167
+ Controller throws --> ProblemDetailsInterceptor (converts to RFC 7807) --> ResponseInterceptor (pass-through if ProblemDetails) --> LoggingInterceptor (logs error) --> Client
168
+ ```
169
+
170
+ | Interceptor | Responsibility |
171
+ |-------------|---------------|
172
+ | `LoggingInterceptor` | Logs request entry/exit, duration, errors. Includes traceId, controller, handler. Emits structured metrics. |
173
+ | `ResponseInterceptor` | Wraps successful responses as `{ success: true, message: data }`. Wraps non-ProblemDetails errors as `{ success: false, error, message, statusCode }`. |
174
+ | `ProblemDetailsInterceptor` | Converts all errors to RFC 7807 ProblemDetails format. Sanitizes sensitive body fields. Adds `debugInfo` in development mode. |
175
+
176
+ ### Distributed Tracing
177
+
178
+ Full request lifecycle tracing through `AsyncLocalStorage`:
179
+
180
+ ```
181
+ Incoming Request
182
+ |
183
+ v
184
+ TraceIdMiddleware -- reads/generates X-Trace-ID, attaches to req & res header
185
+ |
186
+ v
187
+ RequestContextMiddleware -- creates RequestContext in AsyncLocalStorage (traceId, userId, language, startTime)
188
+ |
189
+ v
190
+ TracedLogger -- extends NestJS Logger, auto-prefixes [traceId] to every log line
191
+ |
192
+ v
193
+ LoggingInterceptor -- reads traceId for structured logging
194
+ |
195
+ v
196
+ ProblemDetailsInterceptor -- embeds traceId in error responses
197
+ ```
198
+
199
+ ```typescript
200
+ // Use TracedLogger in any service for automatic traceId injection
201
+ import { TracedLogger } from 'stefaninigo';
202
+
203
+ export class TicketService {
204
+ private readonly logger = new TracedLogger(TicketService.name);
205
+
206
+ findOne(id: string) {
207
+ this.logger.log(`Finding ticket ${id}`);
208
+ // Output: [a1b2c3d4-...] Finding ticket TK-001
209
+ }
210
+ }
211
+
212
+ // Or access context directly
213
+ import { getRequestContext, getTraceId } from 'stefaninigo';
214
+
215
+ const ctx = getRequestContext(); // { traceId, userId, language, startTime }
216
+ const traceId = getTraceId(); // shortcut
217
+ ```
218
+
219
+ ### Event-Driven Architecture
220
+
221
+ `EventBusModule` is a `@Global` module with 3 publishing strategies, toggled via environment variables:
222
+
223
+ ```
224
+ EventBusService.publish(event)
225
+ |
226
+ |-- strategy = 'log' --> Logger output (default, zero infra)
227
+ |-- strategy = 'sns' --> AWS SNS topic (fan-out)
228
+ |-- strategy = 'sqs' --> AWS SQS queue (point-to-point)
229
+ ```
230
+
231
+ ```typescript
232
+ import { EventBusService } from 'stefaninigo';
233
+ import { randomUUID } from 'crypto';
234
+
235
+ @Injectable()
236
+ export class TicketService {
237
+ constructor(private readonly eventBus: EventBusService) {}
238
+
239
+ async create(dto: CreateTicketDto) {
240
+ const ticket = await this.repo.create(dto);
241
+
242
+ await this.eventBus.publish({
243
+ eventId: randomUUID(),
244
+ eventType: 'ticket.created',
245
+ timestamp: new Date().toISOString(),
246
+ providerId: dto.providerId,
247
+ source: 'tickets-service',
248
+ data: { ticketId: ticket.id, clientId: dto.clientId },
249
+ });
250
+
251
+ return ticket;
252
+ }
253
+ }
254
+ ```
255
+
256
+ The library provides typed domain event interfaces for: tickets, routes, geofence, technicians, inventory, clients, locations, contacts, categories, and config. See `events/types/domain-events.ts`.
257
+
258
+ ## Environment Variables
259
+
260
+ ### Database
261
+
262
+ | Variable | Provider | Description |
263
+ |----------|----------|-------------|
264
+ | `database.mongodb.uri` | MongoDB | Connection URI |
265
+ | `database.mongodb.dbName` | MongoDB | Default database name |
266
+ | `database.mongodb.updateAllFields` | MongoDB | Replace vs merge on update |
267
+ | `database.mongodb.returnUpdatedDocument` | MongoDB | Return doc after update |
268
+ | `database.dynamodb.region` | DynamoDB | AWS region |
269
+ | `database.dynamodb.accessKeyId` | DynamoDB | AWS access key |
270
+ | `database.dynamodb.secretAccessKey` | DynamoDB | AWS secret key |
271
+ | `database.postgres.host` | PostgreSQL | Host |
272
+ | `database.postgres.port` | PostgreSQL | Port |
273
+ | `database.postgres.username` | PostgreSQL | Username |
274
+ | `database.postgres.password` | PostgreSQL | Password |
275
+ | `database.postgres.database` | PostgreSQL | Database name |
276
+
277
+ ### Storage
278
+
279
+ | Variable | Provider | Description |
280
+ |----------|----------|-------------|
281
+ | `storage.s3.region` | S3 | AWS region |
282
+ | `storage.s3.accessKeyId` | S3 | AWS access key |
283
+ | `storage.s3.secretAccessKey` | S3 | AWS secret key |
284
+ | `storage.s3.bucket` | S3 | Bucket name |
285
+ | `storage.s3.containerPath` | S3 | Default key prefix |
286
+ | `storage.s3.expiresIn` | S3 | Presigned URL expiry in seconds (default: 3600) |
287
+
288
+ ### Cache
289
+
290
+ | Variable | Provider | Description |
291
+ |----------|----------|-------------|
292
+ | `cache.redis.host` | Redis | Redis host |
293
+ | `cache.redis.port` | Redis | Redis port |
294
+
295
+ ### Messaging
296
+
297
+ | Variable | Provider | Description |
298
+ |----------|----------|-------------|
299
+ | `message.sns.region` | SNS | AWS region |
300
+ | `message.sns.accessKeyId` | SNS | AWS access key |
301
+ | `message.sns.secretAccessKey` | SNS | AWS secret key |
302
+ | `message.sqs.region` | SQS | AWS region |
303
+ | `message.sqs.accessKeyId` | SQS | AWS access key |
304
+ | `message.sqs.secretAccessKey` | SQS | AWS secret key |
305
+ | `message.sqs.queueUrl` | SQS | Default queue URL |
306
+ | `message.sqs.MaxNumberOfMessages` | SQS | Max messages per poll (default: 10) |
307
+ | `message.sqs.WaitTimeSeconds` | SQS | Long poll wait (default: 20) |
308
+ | `message.sqs.pollInterval` | SQS | Poll interval ms (default: 10000) |
309
+
310
+ ### Transport
311
+
312
+ | Variable | Provider | Description |
313
+ |----------|----------|-------------|
314
+ | `transport.aws_ws.domain` | AWS WebSocket | API Gateway WebSocket endpoint |
315
+
316
+ ### EventBus
317
+
318
+ | Variable | Default | Description |
319
+ |----------|---------|-------------|
320
+ | `EVENTS_ENABLED` | `false` | Enable/disable event publishing |
321
+ | `EVENTS_STRATEGY` | `log` | Strategy: `log`, `sns`, or `sqs` |
322
+ | `EVENTS_SNS_TOPIC_ARN` | -- | SNS topic ARN (when strategy=sns) |
323
+ | `EVENTS_SQS_QUEUE_URL` | -- | SQS queue URL (when strategy=sqs) |
324
+
325
+ ### Core
326
+
327
+ | Variable | Default | Description |
328
+ |----------|---------|-------------|
329
+ | `NODE_ENV` | `development` | Controls debug info in error responses |
330
+ | `CORS_ORIGINS` | `*` | Comma-separated allowed origins |
331
+
332
+ ## Module Documentation
333
+
334
+ Each module has its own ARCHITECTURE.md with detailed API reference, usage examples, and configuration:
62
335
 
63
- Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
336
+ - [Core -- Interceptors, Middleware, Context, Logger, Errors, Health](libs/stefaninigo/src/core/ARCHITECTURE.md)
337
+ - [Database -- MongoDB, DynamoDB, PostgreSQL](libs/stefaninigo/src/database/ARCHITECTURE.md)
338
+ - [Storage -- S3 file operations](libs/stefaninigo/src/storage/ARCHITECTURE.md)
339
+ - [Cache -- Redis and Local providers](libs/stefaninigo/src/cache/ARCHITECTURE.md)
340
+ - [Messaging -- AWS SNS and SQS](libs/stefaninigo/src/messaging/ARCHITECTURE.md)
341
+ - [Events -- Domain event bus](libs/stefaninigo/src/events/ARCHITECTURE.md)
342
+ - [Transport -- WebSocket and HTTP](libs/stefaninigo/src/transport/ARCHITECTURE.md)
343
+ - [Config -- Centralized configuration resolver](libs/stefaninigo/src/config/ARCHITECTURE.md)
344
+ - [Geo -- GeoJSON, distance, bounding boxes](libs/stefaninigo/src/geo/ARCHITECTURE.md)
64
345
 
65
- ## Stay in touch
346
+ ## Tech Stack
66
347
 
67
- - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68
- - Website - [https://nestjs.com](https://nestjs.com/)
69
- - Twitter - [@nestframework](https://twitter.com/nestframework)
348
+ | Dependency | Version | Purpose |
349
+ |------------|---------|---------|
350
+ | NestJS | 11.x | Framework |
351
+ | TypeScript | 5.x | Language |
352
+ | MongoDB driver | 6.x | MongoDB provider |
353
+ | pg | 8.x | PostgreSQL provider |
354
+ | AWS SDK v3 | 3.x | S3, SNS, SQS, DynamoDB, API Gateway |
355
+ | ioredis | 5.x | Redis provider |
356
+ | axios | 1.x | HTTP transport |
357
+ | ws | 8.x | WebSocket transport |
70
358
 
71
359
  ## License
72
360
 
73
- Nest is [MIT licensed](LICENSE).
361
+ UNLICENSED -- Internal use only.
@@ -2,6 +2,7 @@ import { CacheServiceInterface } from '../cache-service.interface';
2
2
  export declare class LocalCacheService implements CacheServiceInterface {
3
3
  private readonly config;
4
4
  private cache;
5
+ private timers;
5
6
  constructor(config: {
6
7
  ttl?: number;
7
8
  });
@@ -9,4 +10,5 @@ export declare class LocalCacheService implements CacheServiceInterface {
9
10
  get(key: string): any | null;
10
11
  delete(key: string): void;
11
12
  clear(): void;
13
+ destroy(): void;
12
14
  }
@@ -5,26 +5,55 @@ class LocalCacheService {
5
5
  constructor(config) {
6
6
  this.config = config;
7
7
  this.cache = new Map();
8
+ this.timers = new Map();
8
9
  }
9
10
  set(key, value, ttl) {
10
11
  const expirationTime = ttl || this.config.ttl || 86400000;
12
+ const existingTimer = this.timers.get(key);
13
+ if (existingTimer) {
14
+ clearTimeout(existingTimer);
15
+ }
11
16
  this.cache.set(key, { value, expiresAt: Date.now() + expirationTime });
12
- setTimeout(() => this.cache.delete(key), expirationTime);
17
+ const timer = setTimeout(() => {
18
+ this.cache.delete(key);
19
+ this.timers.delete(key);
20
+ }, expirationTime);
21
+ if (timer.unref) {
22
+ timer.unref();
23
+ }
24
+ this.timers.set(key, timer);
13
25
  }
14
26
  get(key) {
15
27
  const cached = this.cache.get(key);
16
28
  if (!cached || cached.expiresAt < Date.now()) {
17
29
  this.cache.delete(key);
30
+ const timer = this.timers.get(key);
31
+ if (timer) {
32
+ clearTimeout(timer);
33
+ this.timers.delete(key);
34
+ }
18
35
  return null;
19
36
  }
20
37
  return cached.value;
21
38
  }
22
39
  delete(key) {
23
40
  this.cache.delete(key);
41
+ const timer = this.timers.get(key);
42
+ if (timer) {
43
+ clearTimeout(timer);
44
+ this.timers.delete(key);
45
+ }
24
46
  }
25
47
  clear() {
48
+ for (const timer of this.timers.values()) {
49
+ clearTimeout(timer);
50
+ }
51
+ this.timers.clear();
26
52
  this.cache.clear();
27
53
  }
54
+ destroy() {
55
+ this.clear();
56
+ }
28
57
  }
29
58
  exports.LocalCacheService = LocalCacheService;
30
59
  //# sourceMappingURL=loca.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loca.service.js","sourceRoot":"","sources":["../../../../../libs/stefaninigo/src/cache/local/loca.service.ts"],"names":[],"mappings":";;;AAEA,MAAa,iBAAiB;IAG5B,YAA6B,MAAwB;QAAxB,WAAM,GAAN,MAAM,CAAkB;QAF7C,UAAK,GAAqB,IAAI,GAAG,EAAE,CAAC;IAEY,CAAC;IAEzD,GAAG,CAAC,GAAW,EAAE,KAAU,EAAE,GAAY;QACvC,MAAM,cAAc,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC;QAEvE,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;IAC3D,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AA5BD,8CA4BC"}
1
+ {"version":3,"file":"loca.service.js","sourceRoot":"","sources":["../../../../../libs/stefaninigo/src/cache/local/loca.service.ts"],"names":[],"mappings":";;;AAEA,MAAa,iBAAiB;IAI5B,YAA6B,MAAwB;QAAxB,WAAM,GAAN,MAAM,CAAkB;QAH7C,UAAK,GAAqB,IAAI,GAAG,EAAE,CAAC;QACpC,WAAM,GAAgC,IAAI,GAAG,EAAE,CAAC;IAEA,CAAC;IAEzD,GAAG,CAAC,GAAW,EAAE,KAAU,EAAE,GAAY;QACvC,MAAM,cAAc,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC;QAG1D,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,aAAa,CAAC,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC;QAEvE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC,EAAE,cAAc,CAAC,CAAC;QAGnB,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK;QACH,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAOD,OAAO;QACL,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;CACF;AArED,8CAqEC"}
@@ -5,11 +5,25 @@ export interface SwaggerOptions {
5
5
  description: string;
6
6
  version: string;
7
7
  path?: string;
8
+ tags?: Array<{
9
+ name: string;
10
+ description: string;
11
+ }>;
12
+ servers?: Array<{
13
+ url: string;
14
+ description: string;
15
+ }>;
16
+ contact?: {
17
+ name: string;
18
+ url: string;
19
+ email: string;
20
+ };
21
+ bearerAuth?: boolean;
8
22
  }
9
23
  export declare function setupSwagger(app: INestApplication, options: SwaggerOptions): void;
10
24
  export interface CorsOptions {
11
- origins?: string[];
12
- methods?: string[];
25
+ origins?: string | string[];
26
+ methods?: string | string[];
13
27
  credentials?: boolean;
14
28
  }
15
29
  export declare function setupCors(app: INestApplication, options?: CorsOptions): void;
@@ -10,22 +10,62 @@ function createStandardValidationPipe() {
10
10
  whitelist: true,
11
11
  forbidNonWhitelisted: true,
12
12
  transform: true,
13
+ transformOptions: {
14
+ enableImplicitConversion: true,
15
+ },
16
+ validateCustomDecorators: true,
13
17
  });
14
18
  }
15
19
  function setupSwagger(app, options) {
16
- const config = new swagger_1.DocumentBuilder()
20
+ const builder = new swagger_1.DocumentBuilder()
17
21
  .setTitle(options.title)
18
22
  .setDescription(options.description)
19
- .setVersion(options.version)
20
- .addBearerAuth()
21
- .build();
23
+ .setVersion(options.version);
24
+ if (options.bearerAuth !== false) {
25
+ builder.addBearerAuth({
26
+ type: 'http',
27
+ scheme: 'bearer',
28
+ bearerFormat: 'JWT',
29
+ name: 'Authorization',
30
+ description: 'JWT Bearer token',
31
+ in: 'header',
32
+ }, 'bearer');
33
+ }
34
+ if (options.contact) {
35
+ builder.setContact(options.contact.name, options.contact.url, options.contact.email);
36
+ }
37
+ if (options.tags) {
38
+ for (const tag of options.tags) {
39
+ builder.addTag(tag.name, tag.description);
40
+ }
41
+ }
42
+ if (options.servers) {
43
+ for (const server of options.servers) {
44
+ builder.addServer(server.url, server.description);
45
+ }
46
+ }
47
+ const config = builder.build();
22
48
  const document = swagger_1.SwaggerModule.createDocument(app, config);
23
- swagger_1.SwaggerModule.setup(options.path || 'api/docs', app, document);
49
+ const docsPath = options.path || 'api/docs';
50
+ swagger_1.SwaggerModule.setup(docsPath, app, document, {
51
+ swaggerOptions: {
52
+ persistAuthorization: true,
53
+ tagsSorter: 'alpha',
54
+ operationsSorter: 'alpha',
55
+ },
56
+ customSiteTitle: options.title,
57
+ customCss: '.swagger-ui .topbar { display: none }',
58
+ });
59
+ const jsonPath = docsPath.replace(/\/docs$/, '/openapi.json');
60
+ app.getHttpAdapter().get(jsonPath, (_req, res) => {
61
+ res.setHeader('Content-Type', 'application/json');
62
+ res.send(document);
63
+ });
24
64
  }
25
65
  function setupCors(app, options) {
26
66
  app.enableCors({
27
- origin: options?.origins || process.env.CORS_ORIGINS?.split(',') || '*',
28
- methods: options?.methods || ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
67
+ origin: options?.origins || process.env.CORS_ORIGIN || '*',
68
+ methods: options?.methods || 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
29
69
  credentials: options?.credentials ?? true,
30
70
  });
31
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.helpers.js","sourceRoot":"","sources":["../../../../../libs/stefaninigo/src/core/bootstrap/bootstrap.helpers.ts"],"names":[],"mappings":";;AAGA,oEAMC;AASD,oCAaC;AAQD,8BASC;AAhDD,2CAAkE;AAClE,6CAAiE;AAEjE,SAAgB,4BAA4B;IAC1C,OAAO,IAAI,uBAAc,CAAC;QACxB,SAAS,EAAE,IAAI;QACf,oBAAoB,EAAE,IAAI;QAC1B,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;AACL,CAAC;AASD,SAAgB,YAAY,CAC1B,GAAqB,EACrB,OAAuB;IAEvB,MAAM,MAAM,GAAG,IAAI,yBAAe,EAAE;SACjC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;SACvB,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC;SACnC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC;SAC3B,aAAa,EAAE;SACf,KAAK,EAAE,CAAC;IAEX,MAAM,QAAQ,GAAG,uBAAa,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC3D,uBAAa,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;AACjE,CAAC;AAQD,SAAgB,SAAS,CACvB,GAAqB,EACrB,OAAqB;IAErB,GAAG,CAAC,UAAU,CAAC;QACb,MAAM,EAAE,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG;QACvE,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;QACjF,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,IAAI;KAC1C,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"bootstrap.helpers.js","sourceRoot":"","sources":["../../../../../libs/stefaninigo/src/core/bootstrap/bootstrap.helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function getEnvFilePaths(projectRoot?: string): string[];
2
+ export declare function getEnvFilePath(projectRoot?: string): string | null;
3
+ export declare function getEnvironment(): string;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEnvFilePaths = getEnvFilePaths;
4
+ exports.getEnvFilePath = getEnvFilePath;
5
+ exports.getEnvironment = getEnvironment;
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ function getEnvFilePaths(projectRoot = process.cwd()) {
9
+ const nodeEnv = process.env.NODE_ENV || 'development';
10
+ const envFiles = [];
11
+ const envByEnv = path.join(projectRoot, `.env.${nodeEnv}`);
12
+ if (fs.existsSync(envByEnv)) {
13
+ envFiles.push(envByEnv);
14
+ }
15
+ const defaultEnv = path.join(projectRoot, '.env');
16
+ if (fs.existsSync(defaultEnv)) {
17
+ envFiles.push(defaultEnv);
18
+ }
19
+ return envFiles;
20
+ }
21
+ function getEnvFilePath(projectRoot = process.cwd()) {
22
+ const paths = getEnvFilePaths(projectRoot);
23
+ return paths.length > 0 ? paths[0] : null;
24
+ }
25
+ function getEnvironment() {
26
+ return process.env.NODE_ENV || 'development';
27
+ }
28
+ //# sourceMappingURL=env.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.utils.js","sourceRoot":"","sources":["../../../../../libs/stefaninigo/src/core/config/env.utils.ts"],"names":[],"mappings":";;AAaA,0CAeC;AAQD,wCAGC;AAKD,wCAEC;AA9CD,yBAAyB;AACzB,6BAA6B;AAY7B,SAAgB,eAAe,CAAC,cAAsB,OAAO,CAAC,GAAG,EAAE;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;IACtD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,OAAO,EAAE,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAClD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAQD,SAAgB,cAAc,CAAC,cAAsB,OAAO,CAAC,GAAG,EAAE;IAChE,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC;AAKD,SAAgB,cAAc;IAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;AAC/C,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './env.utils';