@vritti/api-sdk 0.1.1 → 0.1.3

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/dist/index.cjs CHANGED
@@ -40,7 +40,7 @@ __export(index_exports, {
40
40
  CsrfGuard: () => CsrfGuard,
41
41
  DEFAULT_CORRELATION_HEADER: () => DEFAULT_CORRELATION_HEADER,
42
42
  DatabaseModule: () => DatabaseModule,
43
- ForbiddenException: () => ForbiddenException2,
43
+ ForbiddenException: () => ForbiddenException,
44
44
  GoneException: () => GoneException,
45
45
  HttpExceptionFilter: () => HttpExceptionFilter,
46
46
  HttpLoggerInterceptor: () => HttpLoggerInterceptor,
@@ -56,13 +56,13 @@ __export(index_exports, {
56
56
  Onboarding: () => Onboarding,
57
57
  PayloadTooLargeException: () => PayloadTooLargeException,
58
58
  PrimaryBaseRepository: () => PrimaryBaseRepository,
59
- PrimaryDatabaseService: () => PrimaryDatabaseService,
59
+ PrimaryDatabaseService: () => PrimaryDatabaseService2,
60
60
  Public: () => Public,
61
61
  RequestTimeoutException: () => RequestTimeoutException,
62
62
  ServiceUnavailableException: () => ServiceUnavailableException,
63
63
  Tenant: () => Tenant,
64
64
  TenantBaseRepository: () => TenantBaseRepository,
65
- TenantContextService: () => TenantContextService,
65
+ TenantContextService: () => TenantContextService2,
66
66
  TenantDatabaseService: () => TenantDatabaseService,
67
67
  TooManyRequestsException: () => TooManyRequestsException,
68
68
  UnauthorizedException: () => UnauthorizedException4,
@@ -71,20 +71,28 @@ __export(index_exports, {
71
71
  ValidationException: () => ValidationException,
72
72
  VrittiAuthGuard: () => VrittiAuthGuard,
73
73
  addCorrelationIdToResponse: () => addCorrelationIdToResponse,
74
+ configureApiSdk: () => configureApiSdk,
74
75
  correlationStorage: () => correlationStorage,
76
+ defineConfig: () => defineConfig,
75
77
  generateCorrelationId: () => generateCorrelationId,
78
+ getConfig: () => getConfig,
76
79
  getCorrelationContext: () => getCorrelationContext,
77
80
  getHttpStatusTitle: () => getHttpStatusTitle,
81
+ getJwtExpiry: () => getJwtExpiry,
82
+ getRefreshCookieOptions: () => getRefreshCookieOptions,
83
+ hashToken: () => hashToken,
84
+ resetConfig: () => resetConfig,
78
85
  runWithCorrelationContext: () => runWithCorrelationContext,
79
- updateCorrelationContext: () => updateCorrelationContext
86
+ updateCorrelationContext: () => updateCorrelationContext,
87
+ verifyTokenHash: () => verifyTokenHash
80
88
  });
81
89
  module.exports = __toCommonJS(index_exports);
82
90
 
83
91
  // src/auth/auth-config.module.ts
84
- var import_common5 = require("@nestjs/common");
85
- var import_config2 = require("@nestjs/config");
86
- var import_core3 = require("@nestjs/core");
87
- var import_jwt2 = require("@nestjs/jwt");
92
+ var import_common4 = require("@nestjs/common");
93
+ var import_config3 = require("@nestjs/config");
94
+ var import_core2 = require("@nestjs/core");
95
+ var import_jwt = require("@nestjs/jwt");
88
96
 
89
97
  // src/request/request.module.ts
90
98
  var import_common2 = require("@nestjs/common");
@@ -92,6 +100,82 @@ var import_common2 = require("@nestjs/common");
92
100
  // src/request/services/request.service.ts
93
101
  var import_common = require("@nestjs/common");
94
102
  var import_core = require("@nestjs/core");
103
+
104
+ // src/config/index.ts
105
+ var defaultConfig = {
106
+ cookie: {
107
+ refreshCookieName: "vritti_refresh",
108
+ refreshCookieMaxAge: 30 * 24 * 60 * 60 * 1e3,
109
+ refreshCookiePath: "/",
110
+ refreshCookieSecure: process.env.NODE_ENV === "production",
111
+ refreshCookieSameSite: "strict"
112
+ },
113
+ jwt: {
114
+ accessTokenExpiry: "15m",
115
+ refreshTokenExpiry: "30d",
116
+ onboardingTokenExpiry: "24h",
117
+ validateTokenBinding: true
118
+ },
119
+ guard: {
120
+ tenantHeaderName: "x-tenant-id",
121
+ authHeaderName: "authorization",
122
+ tokenPrefix: "Bearer"
123
+ }
124
+ };
125
+ var currentConfig = {
126
+ ...defaultConfig
127
+ };
128
+ function defineConfig(config) {
129
+ return config;
130
+ }
131
+ __name(defineConfig, "defineConfig");
132
+ function configureApiSdk(userConfig) {
133
+ currentConfig = {
134
+ cookie: {
135
+ ...defaultConfig.cookie,
136
+ ...userConfig.cookie || {}
137
+ },
138
+ jwt: {
139
+ ...defaultConfig.jwt,
140
+ ...userConfig.jwt || {}
141
+ },
142
+ guard: {
143
+ ...defaultConfig.guard,
144
+ ...userConfig.guard || {}
145
+ }
146
+ };
147
+ }
148
+ __name(configureApiSdk, "configureApiSdk");
149
+ function getConfig() {
150
+ return currentConfig;
151
+ }
152
+ __name(getConfig, "getConfig");
153
+ function resetConfig() {
154
+ currentConfig = {
155
+ ...defaultConfig
156
+ };
157
+ }
158
+ __name(resetConfig, "resetConfig");
159
+ function getRefreshCookieOptions() {
160
+ return {
161
+ httpOnly: true,
162
+ secure: currentConfig.cookie.refreshCookieSecure,
163
+ sameSite: currentConfig.cookie.refreshCookieSameSite,
164
+ path: currentConfig.cookie.refreshCookiePath,
165
+ maxAge: currentConfig.cookie.refreshCookieMaxAge
166
+ };
167
+ }
168
+ __name(getRefreshCookieOptions, "getRefreshCookieOptions");
169
+ function getJwtExpiry() {
170
+ return {
171
+ access: currentConfig.jwt.accessTokenExpiry,
172
+ refresh: currentConfig.jwt.refreshTokenExpiry,
173
+ onboarding: currentConfig.jwt.onboardingTokenExpiry
174
+ };
175
+ }
176
+ __name(getJwtExpiry, "getJwtExpiry");
177
+
178
+ // src/request/services/request.service.ts
95
179
  function _ts_decorate(decorators, target, key, desc) {
96
180
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
97
181
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -109,7 +193,7 @@ function _ts_param(paramIndex, decorator) {
109
193
  };
110
194
  }
111
195
  __name(_ts_param, "_ts_param");
112
- var RequestService = class {
196
+ var RequestService2 = class {
113
197
  static {
114
198
  __name(this, "RequestService");
115
199
  }
@@ -143,21 +227,22 @@ var RequestService = class {
143
227
  return type === "Bearer" && token ? token : null;
144
228
  }
145
229
  /**
146
- * Extract refresh token from session-id cookie
147
- * Cookie name: session-id
230
+ * Extract refresh token from httpOnly cookie
231
+ * Cookie name is configurable via api-sdk config
148
232
  * @returns Refresh token or null if not found
149
233
  */
150
234
  getRefreshToken() {
151
235
  try {
152
236
  const cookies = this.request.cookies;
153
237
  if (cookies && typeof cookies === "object") {
154
- const sessionId = cookies["session-id"];
155
- if (sessionId) {
156
- return sessionId;
238
+ const config = getConfig();
239
+ const refreshToken = cookies[config.cookie.refreshCookieName];
240
+ if (refreshToken) {
241
+ return refreshToken;
157
242
  }
158
243
  }
159
244
  return null;
160
- } catch (error) {
245
+ } catch (_error) {
161
246
  return null;
162
247
  }
163
248
  }
@@ -177,7 +262,7 @@ var RequestService = class {
177
262
  return this.request.headers || {};
178
263
  }
179
264
  };
180
- RequestService = _ts_decorate([
265
+ RequestService2 = _ts_decorate([
181
266
  (0, import_common.Injectable)({
182
267
  scope: import_common.Scope.REQUEST
183
268
  }),
@@ -186,7 +271,7 @@ RequestService = _ts_decorate([
186
271
  _ts_metadata("design:paramtypes", [
187
272
  typeof FastifyRequest === "undefined" ? Object : FastifyRequest
188
273
  ])
189
- ], RequestService);
274
+ ], RequestService2);
190
275
 
191
276
  // src/request/request.module.ts
192
277
  function _ts_decorate2(decorators, target, key, desc) {
@@ -205,31 +290,31 @@ RequestModule = _ts_decorate2([
205
290
  (0, import_common2.Global)(),
206
291
  (0, import_common2.Module)({
207
292
  providers: [
208
- RequestService
293
+ RequestService2
209
294
  ],
210
295
  exports: [
211
- RequestService
296
+ RequestService2
212
297
  ]
213
298
  })
214
299
  ], RequestModule);
215
300
 
216
301
  // src/auth/guards/vritti-auth.guard.ts
217
- var import_common4 = require("@nestjs/common");
218
- var import_config = require("@nestjs/config");
219
- var import_core2 = require("@nestjs/core");
220
- var import_jwt = require("@nestjs/jwt");
221
- var jwt = __toESM(require("jsonwebtoken"), 1);
222
-
223
- // src/database/services/primary-database.service.ts
224
302
  var import_common3 = require("@nestjs/common");
225
- var import_pg = require("pg");
226
- var import_node_postgres = require("drizzle-orm/node-postgres");
227
- var import_drizzle_orm = require("drizzle-orm");
228
303
 
229
- // src/database/constants.ts
230
- var DATABASE_MODULE_OPTIONS = Symbol("DATABASE_MODULE_OPTIONS");
304
+ // src/auth/utils/token-hash.util.ts
305
+ var crypto = __toESM(require("crypto"), 1);
306
+ function hashToken(token) {
307
+ return crypto.createHash("sha256").update(token).digest("hex");
308
+ }
309
+ __name(hashToken, "hashToken");
310
+ function verifyTokenHash(token, expectedHash) {
311
+ const computedHash = hashToken(token);
312
+ if (computedHash.length !== expectedHash.length) return false;
313
+ return crypto.timingSafeEqual(Buffer.from(computedHash, "hex"), Buffer.from(expectedHash, "hex"));
314
+ }
315
+ __name(verifyTokenHash, "verifyTokenHash");
231
316
 
232
- // src/database/services/primary-database.service.ts
317
+ // src/auth/guards/vritti-auth.guard.ts
233
318
  function _ts_decorate3(decorators, target, key, desc) {
234
319
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
235
320
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -241,560 +326,698 @@ function _ts_metadata2(k, v) {
241
326
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
242
327
  }
243
328
  __name(_ts_metadata2, "_ts_metadata");
244
- function _ts_param2(paramIndex, decorator) {
245
- return function(target, key) {
246
- decorator(target, key, paramIndex);
247
- };
248
- }
249
- __name(_ts_param2, "_ts_param");
250
- var PrimaryDatabaseService = class _PrimaryDatabaseService {
329
+ var VrittiAuthGuard = class _VrittiAuthGuard {
251
330
  static {
252
- __name(this, "PrimaryDatabaseService");
331
+ __name(this, "VrittiAuthGuard");
253
332
  }
254
- options;
255
- logger = new import_common3.Logger(_PrimaryDatabaseService.name);
256
- /** PostgreSQL connection pool */
257
- pool = null;
258
- /** Drizzle database instance */
259
- db = null;
260
- /** In-memory cache: Map<tenantIdentifier, TenantConfig> */
261
- tenantConfigCache = /* @__PURE__ */ new Map();
262
- /** Cache TTL in milliseconds */
263
- cacheTTL;
264
- constructor(options) {
265
- this.options = options;
266
- this.cacheTTL = options.connectionCacheTTL || 3e5;
333
+ reflector;
334
+ _configService;
335
+ jwtService;
336
+ primaryDatabase;
337
+ requestService;
338
+ logger = new import_common3.Logger(_VrittiAuthGuard.name);
339
+ constructor(reflector, _configService, jwtService, primaryDatabase, requestService) {
340
+ this.reflector = reflector;
341
+ this._configService = _configService;
342
+ this.jwtService = jwtService;
343
+ this.primaryDatabase = primaryDatabase;
344
+ this.requestService = requestService;
267
345
  }
268
- async onModuleInit() {
269
- if (this.options.primaryDb) {
270
- await this.initializeDrizzleClient();
346
+ async canActivate(context) {
347
+ const request = context.switchToHttp().getRequest();
348
+ const isPublic = this.reflector.getAllAndOverride("isPublic", [
349
+ context.getHandler(),
350
+ context.getClass()
351
+ ]);
352
+ if (isPublic) {
353
+ this.logger.debug("Public endpoint detected, skipping authentication");
354
+ return true;
355
+ }
356
+ const isOnboarding = this.reflector.getAllAndOverride("isOnboarding", [
357
+ context.getHandler(),
358
+ context.getClass()
359
+ ]);
360
+ try {
361
+ const accessToken = this.requestService.getAccessToken();
362
+ if (!accessToken) {
363
+ this.logger.warn("Access token not found in Authorization header");
364
+ throw new import_common3.UnauthorizedException("Access token not found");
365
+ }
366
+ const decodedToken = this.jwtService.decode(accessToken);
367
+ if (!decodedToken) {
368
+ this.logger.warn("Failed to decode access token");
369
+ throw new import_common3.UnauthorizedException("Invalid token format");
370
+ }
371
+ if (isOnboarding) {
372
+ if (decodedToken.type !== "onboarding") {
373
+ this.logger.warn("Onboarding endpoint requires onboarding token");
374
+ throw new import_common3.UnauthorizedException("This endpoint requires an onboarding token");
375
+ }
376
+ const validatedToken2 = this.validateAccessToken(accessToken);
377
+ this.logger.debug("Onboarding token validated successfully");
378
+ this.validateRefreshTokenBinding(context, validatedToken2);
379
+ const userId2 = validatedToken2.userId;
380
+ request.user = {
381
+ id: userId2
382
+ };
383
+ return true;
384
+ }
385
+ if (decodedToken.type === "onboarding") {
386
+ this.logger.warn("Regular endpoint accessed with onboarding token");
387
+ throw new import_common3.UnauthorizedException("Onboarding tokens cannot access this endpoint");
388
+ }
389
+ const validatedToken = this.validateAccessToken(accessToken);
390
+ this.logger.debug("Access token validated successfully");
391
+ this.validateRefreshTokenBinding(context, validatedToken);
392
+ const userId = validatedToken.userId;
393
+ request.user = {
394
+ id: userId
395
+ };
396
+ const tenantIdentifier = this.requestService.getTenantIdentifier();
397
+ if (!tenantIdentifier) {
398
+ this.logger.warn("Tenant identifier not found in request");
399
+ throw new import_common3.UnauthorizedException("Tenant identifier not found");
400
+ }
401
+ this.logger.debug(`Tenant identifier extracted: ${tenantIdentifier}`);
402
+ if (tenantIdentifier === "cloud") {
403
+ this.logger.debug("Platform admin access detected, skipping tenant database validation");
404
+ return true;
405
+ }
406
+ const tenantInfo = await this.primaryDatabase.getTenantInfo(tenantIdentifier);
407
+ if (!tenantInfo) {
408
+ this.logger.warn(`Invalid tenant: ${tenantIdentifier}`);
409
+ throw new import_common3.UnauthorizedException("Invalid tenant");
410
+ }
411
+ if (tenantInfo.status !== "ACTIVE") {
412
+ this.logger.warn(`Tenant ${tenantIdentifier} has status: ${tenantInfo.status}`);
413
+ throw new import_common3.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
414
+ }
415
+ this.logger.debug(`Tenant validated: ${tenantInfo.subdomain} (${tenantInfo.type})`);
416
+ return true;
417
+ } catch (error) {
418
+ if (error instanceof import_common3.UnauthorizedException) {
419
+ throw error;
420
+ }
421
+ this.logger.error("Unexpected error in auth guard", error);
422
+ throw new import_common3.UnauthorizedException("Authentication failed");
271
423
  }
272
424
  }
273
425
  /**
274
- * Initialize connection to primary database using Drizzle
426
+ * Validate access token with proper expiry checks
427
+ * Throws UnauthorizedException if token is invalid or expired
275
428
  */
276
- async initializeDrizzleClient() {
429
+ validateAccessToken(token) {
277
430
  try {
278
- const databaseUrl = this.buildPrimaryDbUrl();
279
- this.pool = new import_pg.Pool({
280
- connectionString: databaseUrl,
281
- max: this.options.maxConnections || 10
282
- });
283
- this.logger.debug(`Schema keys passed to drizzle: [${Object.keys(this.options.drizzleSchema || {}).join(", ")}]`);
284
- this.logger.debug(`Relations keys passed to drizzle: [${Object.keys(this.options.drizzleRelations || {}).join(", ")}]`);
285
- this.db = (0, import_node_postgres.drizzle)({
286
- client: this.pool,
287
- schema: this.options.drizzleSchema,
288
- relations: this.options.drizzleRelations
289
- });
290
- this.logger.debug(`Drizzle query keys after init: [${Object.keys(this.db.query || {}).join(", ")}]`);
291
- await this.pool.query("SELECT 1");
292
- this.logger.log("Connected to primary database (tenant registry)");
431
+ const decoded = this.jwtService.verify(token);
432
+ this.logger.debug(`Access token decoded for user: ${decoded.userId}`);
433
+ if (decoded.exp) {
434
+ const expiryTime = decoded.exp * 1e3;
435
+ const currentTime = Date.now();
436
+ const timeRemaining = expiryTime - currentTime;
437
+ this.logger.debug(`Access token valid for ${Math.floor(timeRemaining / 1e3)} more seconds`);
438
+ }
439
+ return decoded;
293
440
  } catch (error) {
294
- this.logger.error("Failed to connect to primary database", error);
295
- throw new import_common3.InternalServerErrorException("Failed to initialize tenant registry");
441
+ if (error instanceof import_common3.UnauthorizedException) {
442
+ throw error;
443
+ }
444
+ const jwtError = error;
445
+ if (jwtError?.name === "TokenExpiredError") {
446
+ this.logger.warn(`Access token expired at: ${jwtError?.expiredAt}`);
447
+ throw new import_common3.UnauthorizedException("Access token has expired");
448
+ }
449
+ if (jwtError?.name === "JsonWebTokenError") {
450
+ this.logger.warn(`Access token verification failed: ${jwtError?.message}`);
451
+ throw new import_common3.UnauthorizedException("Invalid access token");
452
+ }
453
+ if (jwtError?.name === "NotBeforeError") {
454
+ this.logger.warn("Access token used before valid (nbf claim)");
455
+ throw new import_common3.UnauthorizedException("Access token not yet valid");
456
+ }
457
+ this.logger.error("Unexpected error validating access token", error);
458
+ throw new import_common3.UnauthorizedException("Access token validation failed");
296
459
  }
297
460
  }
298
461
  /**
299
- * Build connection URL from primary database properties
462
+ * Validate that the access token is bound to the refresh token in the cookie.
463
+ * This prevents token theft - a stolen access token is useless without the
464
+ * corresponding refresh token cookie.
465
+ *
466
+ * @param context - The execution context containing the request
467
+ * @param validatedToken - The decoded and validated JWT token
468
+ * @throws UnauthorizedException if token binding validation fails
300
469
  */
301
- buildPrimaryDbUrl() {
302
- if (!this.options.primaryDb) {
303
- throw new Error("Primary database configuration not provided");
470
+ validateRefreshTokenBinding(context, validatedToken) {
471
+ const config = getConfig();
472
+ if (!config.jwt.validateTokenBinding) {
473
+ this.logger.debug("Token binding validation is disabled");
474
+ return;
304
475
  }
305
- const { host, port = 5432, username, password, database, schema = "public", sslMode = "require" } = this.options.primaryDb;
306
- let url = `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
307
- const params = new URLSearchParams();
308
- if (schema) {
309
- params.set("schema", schema);
476
+ if (!validatedToken.refreshTokenHash) {
477
+ this.logger.debug("Token does not contain refreshTokenHash, skipping binding validation");
478
+ return;
310
479
  }
311
- params.set("sslmode", sslMode);
312
- const queryString = params.toString();
313
- if (queryString) {
314
- url += `?${queryString}`;
480
+ const request = context.switchToHttp().getRequest();
481
+ const cookies = request.cookies || {};
482
+ const refreshToken = cookies[config.cookie.refreshCookieName];
483
+ if (!refreshToken) {
484
+ this.logger.warn("Session validation failed - refresh token cookie not found");
485
+ throw new import_common3.UnauthorizedException("Session validation failed");
315
486
  }
316
- this.logger.debug(`Primary DB connection URL: ${this.maskPassword(url)}`);
317
- return url;
487
+ if (!verifyTokenHash(refreshToken, validatedToken.refreshTokenHash)) {
488
+ this.logger.warn("Session validation failed - token binding mismatch");
489
+ throw new import_common3.UnauthorizedException("Session validation failed");
490
+ }
491
+ this.logger.debug("Token binding validated successfully");
318
492
  }
319
- /**
320
- * Mask password in connection URL for logging
321
- */
322
- maskPassword(url) {
323
- return url.replace(/:([^@]+)@/, ":****@");
493
+ };
494
+ VrittiAuthGuard = _ts_decorate3([
495
+ (0, import_common3.Injectable)({
496
+ scope: import_common3.Scope.REQUEST
497
+ }),
498
+ _ts_metadata2("design:type", Function),
499
+ _ts_metadata2("design:paramtypes", [
500
+ typeof Reflector === "undefined" ? Object : Reflector,
501
+ typeof ConfigService === "undefined" ? Object : ConfigService,
502
+ typeof JwtService === "undefined" ? Object : JwtService,
503
+ typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
504
+ typeof RequestService === "undefined" ? Object : RequestService
505
+ ])
506
+ ], VrittiAuthGuard);
507
+
508
+ // src/auth/auth-config.module.ts
509
+ function _ts_decorate4(decorators, target, key, desc) {
510
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
511
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
512
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
513
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
514
+ }
515
+ __name(_ts_decorate4, "_ts_decorate");
516
+ var AuthConfigModule = class _AuthConfigModule {
517
+ static {
518
+ __name(this, "AuthConfigModule");
324
519
  }
325
520
  /**
326
- * Get tenant configuration by identifier (ID or subdomain)
521
+ * Register the auth module with async configuration
327
522
  *
328
- * @param tenantIdentifier Tenant ID or subdomain
329
- * @returns Tenant configuration or null if not found
523
+ * This method:
524
+ * 1. Configures JwtModule with JWT_SECRET from ConfigService
525
+ * 2. Provides VrittiAuthGuard globally (applies to all routes)
526
+ * 3. Exports JwtModule for use in other modules (e.g., for signing tokens)
527
+ *
528
+ * @returns Dynamic module configuration
330
529
  */
331
- async getTenantInfo(tenantIdentifier) {
332
- const cached = this.tenantConfigCache.get(tenantIdentifier);
333
- if (cached) {
334
- this.logger.debug(`Cache hit for tenant: ${tenantIdentifier}`);
335
- return cached;
336
- }
337
- try {
338
- if (!this.db) {
339
- throw new Error("Primary database client not initialized");
340
- }
341
- this.logger.debug(`Querying primary database for tenant: ${tenantIdentifier}`);
342
- const schema = this.options.drizzleSchema;
343
- const { tenants, tenantDatabaseConfigs } = schema;
344
- const result = await this.db.select().from(tenants).leftJoin(tenantDatabaseConfigs, (0, import_drizzle_orm.eq)(tenants.id, tenantDatabaseConfigs.tenantId)).where((0, import_drizzle_orm.or)((0, import_drizzle_orm.eq)(tenants.id, tenantIdentifier), (0, import_drizzle_orm.eq)(tenants.subdomain, tenantIdentifier))).limit(1);
345
- if (!result.length) {
346
- this.logger.warn(`Tenant not found: ${tenantIdentifier}`);
347
- return null;
348
- }
349
- const row = result[0];
350
- const tenant = row.tenants;
351
- const config = row.tenant_database_configs;
352
- if (tenant.status !== "ACTIVE") {
353
- this.logger.warn(`Tenant not active: ${tenantIdentifier}`);
354
- return null;
355
- }
356
- const info = {
357
- id: tenant.id,
358
- subdomain: tenant.subdomain,
359
- type: tenant.dbType,
360
- status: tenant.status,
361
- // For SHARED tenants: schema name
362
- schemaName: config?.dbSchema || void 0,
363
- // For DEDICATED tenants: database configuration from TenantDatabaseConfig table
364
- databaseName: config?.dbName || void 0,
365
- databaseHost: config?.dbHost || void 0,
366
- databasePort: config?.dbPort || void 0,
367
- databaseUsername: config?.dbUsername ? this.decrypt(config.dbUsername) : void 0,
368
- databasePassword: config?.dbPassword ? this.decrypt(config.dbPassword) : void 0,
369
- databaseSslMode: config?.dbSslMode || void 0,
370
- connectionPoolSize: config?.connectionPoolSize || void 0
371
- };
372
- this.cacheInfo(info);
373
- return info;
374
- } catch (error) {
375
- this.logger.error(`Failed to fetch tenant info: ${tenantIdentifier}`, error);
376
- throw new import_common3.InternalServerErrorException("Failed to resolve tenant");
377
- }
378
- }
379
- /**
380
- * Cache tenant information with TTL
381
- */
382
- cacheInfo(info) {
383
- this.tenantConfigCache.set(info.id, info);
384
- this.tenantConfigCache.set(info.subdomain, info);
385
- setTimeout(() => {
386
- this.tenantConfigCache.delete(info.id);
387
- this.tenantConfigCache.delete(info.subdomain);
388
- this.logger.debug(`Cache expired for tenant: ${info.subdomain}`);
389
- }, this.cacheTTL);
530
+ static forRootAsync() {
531
+ return {
532
+ module: _AuthConfigModule,
533
+ imports: [
534
+ import_config3.ConfigModule,
535
+ RequestModule,
536
+ import_jwt.JwtModule.registerAsync({
537
+ imports: [
538
+ import_config3.ConfigModule
539
+ ],
540
+ inject: [
541
+ import_config3.ConfigService
542
+ ],
543
+ useFactory: /* @__PURE__ */ __name((config) => ({
544
+ secret: config.get("JWT_SECRET"),
545
+ signOptions: {
546
+ algorithm: "HS256"
547
+ }
548
+ }), "useFactory")
549
+ })
550
+ ],
551
+ providers: [
552
+ {
553
+ provide: import_core2.APP_GUARD,
554
+ useClass: VrittiAuthGuard
555
+ }
556
+ ],
557
+ exports: [
558
+ import_jwt.JwtModule
559
+ ]
560
+ };
390
561
  }
391
- /**
392
- * Clear cached tenant information
393
- *
394
- * Useful when tenant settings are updated and cache needs to be invalidated
395
- *
396
- * @param tenantIdentifier Tenant ID or subdomain
397
- */
398
- clearTenantCache(tenantIdentifier) {
399
- const config = this.tenantConfigCache.get(tenantIdentifier);
400
- if (config) {
401
- this.tenantConfigCache.delete(config.id);
402
- this.tenantConfigCache.delete(config.subdomain);
403
- this.logger.log(`Cleared cache for tenant: ${tenantIdentifier}`);
404
- }
562
+ };
563
+ AuthConfigModule = _ts_decorate4([
564
+ (0, import_common4.Global)(),
565
+ (0, import_common4.Module)({})
566
+ ], AuthConfigModule);
567
+
568
+ // src/auth/decorators/onboarding.decorator.ts
569
+ var import_common5 = require("@nestjs/common");
570
+ var Onboarding = /* @__PURE__ */ __name(() => (0, import_common5.SetMetadata)("isOnboarding", true), "Onboarding");
571
+
572
+ // src/auth/decorators/public.decorator.ts
573
+ var import_common6 = require("@nestjs/common");
574
+ var Public = /* @__PURE__ */ __name(() => (0, import_common6.SetMetadata)("isPublic", true), "Public");
575
+
576
+ // src/database/database.module.ts
577
+ var import_common12 = require("@nestjs/common");
578
+ var import_core3 = require("@nestjs/core");
579
+
580
+ // src/database/constants.ts
581
+ var DATABASE_MODULE_OPTIONS = Symbol("DATABASE_MODULE_OPTIONS");
582
+
583
+ // src/database/interceptors/message-tenant-context.interceptor.ts
584
+ var import_common7 = require("@nestjs/common");
585
+ var import_operators = require("rxjs/operators");
586
+ function _ts_decorate5(decorators, target, key, desc) {
587
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
588
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
589
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
590
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
591
+ }
592
+ __name(_ts_decorate5, "_ts_decorate");
593
+ function _ts_metadata3(k, v) {
594
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
595
+ }
596
+ __name(_ts_metadata3, "_ts_metadata");
597
+ var MessageTenantContextInterceptor = class _MessageTenantContextInterceptor {
598
+ static {
599
+ __name(this, "MessageTenantContextInterceptor");
405
600
  }
406
- /**
407
- * Clear all cached tenant configurations
408
- */
409
- clearAllCaches() {
410
- const size = this.tenantConfigCache.size;
411
- this.tenantConfigCache.clear();
412
- this.logger.log(`Cleared ${size} cached tenant configs`);
601
+ tenantContext;
602
+ logger = new import_common7.Logger(_MessageTenantContextInterceptor.name);
603
+ constructor(tenantContext) {
604
+ this.tenantContext = tenantContext;
413
605
  }
414
- /**
415
- * Get the Drizzle database instance for the primary database.
416
- * This is a synchronous property that returns the initialized Drizzle client.
417
- *
418
- * @returns Primary database Drizzle instance
419
- * @throws Error if primary database client is not initialized
420
- */
421
- get drizzleClient() {
422
- if (!this.db) {
423
- throw new Error("Primary database client not initialized");
606
+ intercept(context, next) {
607
+ const contextType = context.getType();
608
+ if (contextType === "rpc") {
609
+ const rpcContext = context.switchToRpc();
610
+ const payload = rpcContext.getData();
611
+ if (payload?.tenant) {
612
+ const tenant = payload.tenant;
613
+ this.logger.debug(`Setting tenant context from message: ${tenant.subdomain}`);
614
+ try {
615
+ this.tenantContext.setTenant(tenant);
616
+ this.logger.log(`Tenant context set: ${tenant.subdomain} (${tenant.type})`);
617
+ } catch (error) {
618
+ this.logger.error("Failed to set tenant context from message", error);
619
+ }
620
+ } else {
621
+ this.logger.warn("Message payload missing tenant information");
622
+ }
424
623
  }
425
- return this.db;
426
- }
427
- /**
428
- * Get the Drizzle schema
429
- */
430
- get schema() {
431
- return this.options.drizzleSchema;
624
+ return next.handle().pipe((0, import_operators.tap)({
625
+ next: /* @__PURE__ */ __name(() => {
626
+ this.cleanupContext();
627
+ }, "next"),
628
+ error: /* @__PURE__ */ __name(() => {
629
+ this.cleanupContext();
630
+ }, "error"),
631
+ complete: /* @__PURE__ */ __name(() => {
632
+ this.cleanupContext();
633
+ }, "complete")
634
+ }));
432
635
  }
433
636
  /**
434
- * Decrypt database credentials
435
- *
436
- * Override this method to implement your encryption strategy
437
- *
438
- * @param encrypted Encrypted value
439
- * @returns Decrypted value
637
+ * Clean up tenant context after message is processed
440
638
  */
441
- decrypt(encrypted) {
442
- return encrypted;
443
- }
444
- async onModuleDestroy() {
445
- if (this.pool) {
446
- await this.pool.end();
447
- this.logger.log("Disconnected from primary database");
639
+ cleanupContext() {
640
+ if (this.tenantContext.hasTenant()) {
641
+ const tenant = this.tenantContext.getTenantIdSafe();
642
+ this.tenantContext.clearTenant();
643
+ this.logger.debug(`Cleaned up tenant context: ${tenant}`);
448
644
  }
449
645
  }
450
646
  };
451
- PrimaryDatabaseService = _ts_decorate3([
452
- (0, import_common3.Injectable)(),
453
- _ts_param2(0, (0, import_common3.Inject)(DATABASE_MODULE_OPTIONS)),
454
- _ts_metadata2("design:type", Function),
455
- _ts_metadata2("design:paramtypes", [
456
- typeof DatabaseModuleOptions === "undefined" ? Object : DatabaseModuleOptions
647
+ MessageTenantContextInterceptor = _ts_decorate5([
648
+ (0, import_common7.Injectable)({
649
+ scope: import_common7.Scope.REQUEST
650
+ }),
651
+ _ts_metadata3("design:type", Function),
652
+ _ts_metadata3("design:paramtypes", [
653
+ typeof TenantContextService === "undefined" ? Object : TenantContextService
457
654
  ])
458
- ], PrimaryDatabaseService);
655
+ ], MessageTenantContextInterceptor);
459
656
 
460
- // src/auth/guards/vritti-auth.guard.ts
461
- function _ts_decorate4(decorators, target, key, desc) {
657
+ // src/database/interceptors/tenant-context.interceptor.ts
658
+ var import_common8 = require("@nestjs/common");
659
+ function _ts_decorate6(decorators, target, key, desc) {
462
660
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
463
661
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
464
662
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
465
663
  return c > 3 && r && Object.defineProperty(target, key, r), r;
466
664
  }
467
- __name(_ts_decorate4, "_ts_decorate");
468
- function _ts_metadata3(k, v) {
665
+ __name(_ts_decorate6, "_ts_decorate");
666
+ function _ts_metadata4(k, v) {
469
667
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
470
668
  }
471
- __name(_ts_metadata3, "_ts_metadata");
472
- var VrittiAuthGuard = class _VrittiAuthGuard {
669
+ __name(_ts_metadata4, "_ts_metadata");
670
+ var TenantContextInterceptor = class _TenantContextInterceptor {
473
671
  static {
474
- __name(this, "VrittiAuthGuard");
672
+ __name(this, "TenantContextInterceptor");
475
673
  }
476
674
  reflector;
477
- configService;
478
- jwtService;
675
+ tenantContext;
479
676
  primaryDatabase;
480
677
  requestService;
481
- logger = new import_common4.Logger(_VrittiAuthGuard.name);
482
- constructor(reflector, configService, jwtService, primaryDatabase, requestService) {
678
+ logger = new import_common8.Logger(_TenantContextInterceptor.name);
679
+ constructor(reflector, tenantContext, primaryDatabase, requestService) {
483
680
  this.reflector = reflector;
484
- this.configService = configService;
485
- this.jwtService = jwtService;
681
+ this.tenantContext = tenantContext;
486
682
  this.primaryDatabase = primaryDatabase;
487
683
  this.requestService = requestService;
488
684
  }
489
- async canActivate(context) {
685
+ async intercept(context, next) {
490
686
  const request = context.switchToHttp().getRequest();
687
+ this.logger.debug(`Processing request: ${request.method} ${request.url}`);
491
688
  const isPublic = this.reflector.getAllAndOverride("isPublic", [
492
689
  context.getHandler(),
493
690
  context.getClass()
494
691
  ]);
495
- if (isPublic) {
496
- this.logger.debug("Public endpoint detected, skipping authentication");
497
- return true;
498
- }
499
- const isOnboarding = this.reflector.getAllAndOverride("isOnboarding", [
500
- context.getHandler(),
501
- context.getClass()
502
- ]);
503
692
  try {
504
- const accessToken = this.requestService.getAccessToken();
505
- if (!accessToken) {
506
- this.logger.warn("Access token not found in Authorization header");
507
- throw new import_common4.UnauthorizedException("Access token not found");
508
- }
509
- const decodedToken = this.jwtService.decode(accessToken);
510
- if (!decodedToken) {
511
- this.logger.warn("Failed to decode access token");
512
- throw new import_common4.UnauthorizedException("Invalid token format");
693
+ const tenantIdentifier = this.requestService.getTenantIdentifier();
694
+ if (isPublic && !tenantIdentifier) {
695
+ this.logger.debug("Public endpoint without tenant identifier, skipping tenant context setup");
696
+ return next.handle();
513
697
  }
514
- if (isOnboarding) {
515
- if (decodedToken.type !== "onboarding") {
516
- this.logger.warn("Onboarding endpoint requires onboarding token");
517
- throw new import_common4.UnauthorizedException("This endpoint requires an onboarding token");
518
- }
519
- const validatedToken2 = this.validateAccessToken(accessToken);
520
- this.logger.debug("Onboarding token validated successfully");
521
- const userId2 = validatedToken2.userId;
522
- request.user = {
523
- id: userId2
524
- };
525
- return true;
698
+ if (!tenantIdentifier) {
699
+ throw new import_common8.UnauthorizedException("Tenant identifier not found in request");
526
700
  }
527
- if (decodedToken.type === "onboarding") {
528
- this.logger.warn("Regular endpoint accessed with onboarding token");
529
- throw new import_common4.UnauthorizedException("Onboarding tokens cannot access this endpoint");
530
- }
531
- const validatedToken = this.validateAccessToken(accessToken);
532
- this.logger.debug("Access token validated successfully");
533
- const refreshToken = this.requestService.getRefreshToken();
534
- if (!refreshToken) {
535
- this.logger.warn("Refresh token (session-id) not found in cookies");
536
- throw new import_common4.UnauthorizedException("Refresh token not found");
537
- }
538
- this.validateRefreshToken(refreshToken);
539
- this.logger.debug("Refresh token validated successfully");
540
- const userId = validatedToken.userId;
541
- request.user = {
542
- id: userId
543
- };
544
- const tenantIdentifier = this.requestService.getTenantIdentifier();
545
- if (!tenantIdentifier) {
546
- this.logger.warn("Tenant identifier not found in request");
547
- throw new import_common4.UnauthorizedException("Tenant identifier not found");
548
- }
549
- this.logger.debug(`Tenant identifier extracted: ${tenantIdentifier}`);
550
- if (tenantIdentifier === "cloud") {
551
- this.logger.debug("Platform admin access detected, skipping tenant database validation");
552
- return true;
701
+ this.logger.debug(`Tenant identifier extracted: ${tenantIdentifier}`);
702
+ if (tenantIdentifier === "cloud") {
703
+ this.logger.log("Cloud platform access detected, skipping tenant context setup");
704
+ return next.handle();
553
705
  }
554
706
  const tenantInfo = await this.primaryDatabase.getTenantInfo(tenantIdentifier);
555
707
  if (!tenantInfo) {
556
708
  this.logger.warn(`Invalid tenant: ${tenantIdentifier}`);
557
- throw new import_common4.UnauthorizedException("Invalid tenant");
709
+ throw new import_common8.UnauthorizedException("Invalid tenant");
558
710
  }
559
711
  if (tenantInfo.status !== "ACTIVE") {
560
712
  this.logger.warn(`Tenant ${tenantIdentifier} has status: ${tenantInfo.status}`);
561
- throw new import_common4.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
562
- }
563
- this.logger.debug(`Tenant validated: ${tenantInfo.subdomain} (${tenantInfo.type})`);
564
- return true;
565
- } catch (error) {
566
- if (error instanceof import_common4.UnauthorizedException) {
567
- throw error;
568
- }
569
- this.logger.error("Unexpected error in auth guard", error);
570
- throw new import_common4.UnauthorizedException("Authentication failed");
571
- }
572
- }
573
- /**
574
- * Validate access token with proper expiry checks
575
- * Throws UnauthorizedException if token is invalid or expired
576
- */
577
- validateAccessToken(token) {
578
- try {
579
- const decoded = this.jwtService.verify(token);
580
- this.logger.debug(`Access token decoded for user: ${decoded.userId}`);
581
- if (decoded.exp) {
582
- const expiryTime = decoded.exp * 1e3;
583
- const currentTime = Date.now();
584
- const timeRemaining = expiryTime - currentTime;
585
- this.logger.debug(`Access token valid for ${Math.floor(timeRemaining / 1e3)} more seconds`);
586
- }
587
- return decoded;
588
- } catch (error) {
589
- if (error instanceof import_common4.UnauthorizedException) {
590
- throw error;
591
- }
592
- const jwtError = error;
593
- if (jwtError?.name === "TokenExpiredError") {
594
- this.logger.warn(`Access token expired at: ${jwtError?.expiredAt}`);
595
- throw new import_common4.UnauthorizedException("Access token has expired");
596
- }
597
- if (jwtError?.name === "JsonWebTokenError") {
598
- this.logger.warn(`Access token verification failed: ${jwtError?.message}`);
599
- throw new import_common4.UnauthorizedException("Invalid access token");
600
- }
601
- if (jwtError?.name === "NotBeforeError") {
602
- this.logger.warn("Access token used before valid (nbf claim)");
603
- throw new import_common4.UnauthorizedException("Access token not yet valid");
604
- }
605
- this.logger.error("Unexpected error validating access token", error);
606
- throw new import_common4.UnauthorizedException("Access token validation failed");
607
- }
608
- }
609
- /**
610
- * Validate refresh token with proper expiry checks
611
- * Throws UnauthorizedException if token is invalid or expired
612
- */
613
- validateRefreshToken(token) {
614
- const jwtSecret = this.configService.get("JWT_REFRESH_SECRET") || this.configService.get("JWT_SECRET");
615
- this.validateRefreshTokenWithSecret(token, jwtSecret);
616
- }
617
- /**
618
- * Helper to validate refresh token with specific secret
619
- */
620
- validateRefreshTokenWithSecret(token, secret) {
621
- if (!secret) {
622
- this.logger.error("JWT secret not configured for refresh token validation");
623
- throw new import_common4.UnauthorizedException("Server configuration error");
624
- }
625
- try {
626
- const decoded = jwt.verify(token, secret, {
627
- algorithms: [
628
- "HS256",
629
- "HS512",
630
- "RS256"
631
- ]
632
- });
633
- this.logger.debug(`Refresh token decoded for user: ${decoded.userId}`);
634
- if (decoded.exp) {
635
- const expiryTime = decoded.exp * 1e3;
636
- const currentTime = Date.now();
637
- if (currentTime > expiryTime) {
638
- this.logger.warn("Refresh token has expired");
639
- throw new import_common4.UnauthorizedException("Refresh token has expired. Please login again");
640
- }
641
- const timeRemaining = expiryTime - currentTime;
642
- this.logger.debug(`Refresh token valid for ${Math.floor(timeRemaining / 1e3)} more seconds`);
713
+ throw new import_common8.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
643
714
  }
715
+ this.logger.debug(`Tenant config loaded: ${tenantInfo.subdomain} (${tenantInfo.type})`);
716
+ this.tenantContext.setTenant(tenantInfo);
717
+ request.tenant = tenantInfo;
718
+ this.logger.log(`Tenant context set: ${tenantInfo.subdomain}`);
644
719
  } catch (error) {
645
- if (error instanceof import_common4.UnauthorizedException) {
646
- throw error;
647
- }
648
- const jwtError = error;
649
- if (jwtError?.name === "TokenExpiredError") {
650
- this.logger.warn(`Refresh token expired at: ${jwtError?.expiredAt}`);
651
- throw new import_common4.UnauthorizedException("Refresh token has expired. Please login again");
652
- }
653
- if (jwtError?.name === "JsonWebTokenError") {
654
- this.logger.warn(`Refresh token verification failed: ${jwtError?.message}`);
655
- throw new import_common4.UnauthorizedException("Invalid refresh token");
656
- }
657
- if (jwtError?.name === "NotBeforeError") {
658
- this.logger.warn("Refresh token used before valid (nbf claim)");
659
- throw new import_common4.UnauthorizedException("Refresh token not yet valid");
660
- }
661
- this.logger.error("Unexpected error validating refresh token", error);
662
- throw new import_common4.UnauthorizedException("Refresh token validation failed");
720
+ this.logger.error("Failed to set tenant context", error);
721
+ throw error;
663
722
  }
723
+ return next.handle();
664
724
  }
665
725
  };
666
- VrittiAuthGuard = _ts_decorate4([
667
- (0, import_common4.Injectable)({
668
- scope: import_common4.Scope.REQUEST
726
+ TenantContextInterceptor = _ts_decorate6([
727
+ (0, import_common8.Injectable)({
728
+ scope: import_common8.Scope.REQUEST
669
729
  }),
670
- _ts_metadata3("design:type", Function),
671
- _ts_metadata3("design:paramtypes", [
672
- typeof import_core2.Reflector === "undefined" ? Object : import_core2.Reflector,
673
- typeof import_config.ConfigService === "undefined" ? Object : import_config.ConfigService,
674
- typeof import_jwt.JwtService === "undefined" ? Object : import_jwt.JwtService,
730
+ _ts_metadata4("design:type", Function),
731
+ _ts_metadata4("design:paramtypes", [
732
+ typeof Reflector === "undefined" ? Object : Reflector,
733
+ typeof TenantContextService === "undefined" ? Object : TenantContextService,
675
734
  typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
676
735
  typeof RequestService === "undefined" ? Object : RequestService
677
736
  ])
678
- ], VrittiAuthGuard);
737
+ ], TenantContextInterceptor);
679
738
 
680
- // src/auth/auth-config.module.ts
681
- function _ts_decorate5(decorators, target, key, desc) {
739
+ // src/database/services/primary-database.service.ts
740
+ var import_common9 = require("@nestjs/common");
741
+ var import_drizzle_orm = require("drizzle-orm");
742
+ var import_node_postgres = require("drizzle-orm/node-postgres");
743
+ var import_pg = require("pg");
744
+ function _ts_decorate7(decorators, target, key, desc) {
682
745
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
683
746
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
684
747
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
685
748
  return c > 3 && r && Object.defineProperty(target, key, r), r;
686
749
  }
687
- __name(_ts_decorate5, "_ts_decorate");
688
- var AuthConfigModule = class _AuthConfigModule {
750
+ __name(_ts_decorate7, "_ts_decorate");
751
+ function _ts_metadata5(k, v) {
752
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
753
+ }
754
+ __name(_ts_metadata5, "_ts_metadata");
755
+ function _ts_param2(paramIndex, decorator) {
756
+ return function(target, key) {
757
+ decorator(target, key, paramIndex);
758
+ };
759
+ }
760
+ __name(_ts_param2, "_ts_param");
761
+ var PrimaryDatabaseService2 = class _PrimaryDatabaseService {
689
762
  static {
690
- __name(this, "AuthConfigModule");
763
+ __name(this, "PrimaryDatabaseService");
691
764
  }
692
- /**
693
- * Register the auth module with async configuration
694
- *
695
- * This method:
696
- * 1. Configures JwtModule with JWT_SECRET from ConfigService
697
- * 2. Provides VrittiAuthGuard globally (applies to all routes)
698
- * 3. Exports JwtModule for use in other modules (e.g., for signing tokens)
699
- *
700
- * @returns Dynamic module configuration
701
- */
702
- static forRootAsync() {
703
- return {
704
- module: _AuthConfigModule,
705
- imports: [
706
- import_config2.ConfigModule,
707
- RequestModule,
708
- import_jwt2.JwtModule.registerAsync({
709
- imports: [
710
- import_config2.ConfigModule
711
- ],
712
- inject: [
713
- import_config2.ConfigService
714
- ],
715
- useFactory: /* @__PURE__ */ __name((config) => ({
716
- secret: config.get("JWT_SECRET"),
717
- signOptions: {
718
- algorithm: "HS256"
719
- }
720
- }), "useFactory")
721
- })
722
- ],
723
- providers: [
724
- {
725
- provide: import_core3.APP_GUARD,
726
- useClass: VrittiAuthGuard
727
- }
728
- ],
729
- exports: [
730
- import_jwt2.JwtModule
731
- ]
732
- };
765
+ options;
766
+ logger = new import_common9.Logger(_PrimaryDatabaseService.name);
767
+ /** PostgreSQL connection pool */
768
+ pool = null;
769
+ /** Drizzle database instance */
770
+ db = null;
771
+ /** In-memory cache: Map<tenantIdentifier, TenantConfig> */
772
+ tenantConfigCache = /* @__PURE__ */ new Map();
773
+ /** Cache TTL in milliseconds */
774
+ cacheTTL;
775
+ constructor(options) {
776
+ this.options = options;
777
+ this.cacheTTL = options.connectionCacheTTL || 3e5;
733
778
  }
734
- };
735
- AuthConfigModule = _ts_decorate5([
736
- (0, import_common5.Global)(),
737
- (0, import_common5.Module)({})
738
- ], AuthConfigModule);
739
-
740
- // src/database/database.module.ts
741
- var import_common10 = require("@nestjs/common");
742
- var import_core5 = require("@nestjs/core");
743
-
744
- // src/database/interceptors/message-tenant-context.interceptor.ts
745
- var import_common7 = require("@nestjs/common");
746
- var import_operators = require("rxjs/operators");
747
-
748
- // src/database/services/tenant-context.service.ts
749
- var import_common6 = require("@nestjs/common");
750
- function _ts_decorate6(decorators, target, key, desc) {
751
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
752
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
753
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
754
- return c > 3 && r && Object.defineProperty(target, key, r), r;
755
- }
756
- __name(_ts_decorate6, "_ts_decorate");
757
- var TenantContextService = class {
758
- static {
759
- __name(this, "TenantContextService");
779
+ async onModuleInit() {
780
+ if (this.options.primaryDb) {
781
+ await this.initializeDrizzleClient();
782
+ }
760
783
  }
761
- tenantInfo = null;
762
784
  /**
763
- * Set tenant information for this request/message
764
- *
765
- * This is typically called by:
766
- * - TenantContextInterceptor (for HTTP requests in gateway)
767
- * - MessageTenantContextInterceptor (for RabbitMQ messages in microservices)
768
- * - Manual context setup in message handlers
769
- *
770
- * @param tenantInfo Complete tenant information
771
- * @throws Error if tenant context is already set (prevents accidental overwrites)
785
+ * Initialize connection to primary database using Drizzle
772
786
  */
773
- setTenant(tenantInfo) {
774
- if (this.tenantInfo) {
775
- throw new Error("Tenant context already set for this request");
787
+ async initializeDrizzleClient() {
788
+ try {
789
+ const databaseUrl = this.buildPrimaryDbUrl();
790
+ this.pool = new import_pg.Pool({
791
+ connectionString: databaseUrl,
792
+ max: this.options.maxConnections || 10
793
+ });
794
+ this.logger.debug(`Schema keys passed to drizzle: [${Object.keys(this.options.drizzleSchema || {}).join(", ")}]`);
795
+ this.logger.debug(`Relations keys passed to drizzle: [${Object.keys(this.options.drizzleRelations || {}).join(", ")}]`);
796
+ this.db = (0, import_node_postgres.drizzle)({
797
+ client: this.pool,
798
+ schema: this.options.drizzleSchema,
799
+ relations: this.options.drizzleRelations
800
+ });
801
+ this.logger.debug(`Drizzle query keys after init: [${Object.keys(this.db.query || {}).join(", ")}]`);
802
+ await this.pool.query("SELECT 1");
803
+ this.logger.log("Connected to primary database (tenant registry)");
804
+ } catch (error) {
805
+ this.logger.error("Failed to connect to primary database", error);
806
+ throw new import_common9.InternalServerErrorException("Failed to initialize tenant registry");
776
807
  }
777
- this.tenantInfo = tenantInfo;
778
808
  }
779
809
  /**
780
- * Get tenant information for this request/message
781
- *
782
- * @returns Tenant information
783
- * @throws UnauthorizedException if tenant context hasn't been set
810
+ * Build connection URL from primary database properties
784
811
  */
785
- getTenant() {
786
- if (!this.tenantInfo) {
787
- throw new import_common6.UnauthorizedException("Tenant context not set");
812
+ buildPrimaryDbUrl() {
813
+ if (!this.options.primaryDb) {
814
+ throw new Error("Primary database configuration not provided");
788
815
  }
789
- return this.tenantInfo;
816
+ const { host, port = 5432, username, password, database, schema = "public", sslMode = "require" } = this.options.primaryDb;
817
+ let url = `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
818
+ const params = new URLSearchParams();
819
+ if (schema) {
820
+ params.set("schema", schema);
821
+ }
822
+ params.set("sslmode", sslMode);
823
+ const queryString = params.toString();
824
+ if (queryString) {
825
+ url += `?${queryString}`;
826
+ }
827
+ this.logger.debug(`Primary DB connection URL: ${this.maskPassword(url)}`);
828
+ return url;
790
829
  }
791
830
  /**
792
- * Check if tenant context has been set
793
- *
794
- * @returns true if tenant context is available
831
+ * Mask password in connection URL for logging
795
832
  */
796
- hasTenant() {
797
- return this.tenantInfo !== null;
833
+ maskPassword(url) {
834
+ return url.replace(/:([^@]+)@/, ":****@");
835
+ }
836
+ /**
837
+ * Get tenant configuration by identifier (ID or subdomain)
838
+ *
839
+ * @param tenantIdentifier Tenant ID or subdomain
840
+ * @returns Tenant configuration or null if not found
841
+ */
842
+ async getTenantInfo(tenantIdentifier) {
843
+ const cached = this.tenantConfigCache.get(tenantIdentifier);
844
+ if (cached) {
845
+ this.logger.debug(`Cache hit for tenant: ${tenantIdentifier}`);
846
+ return cached;
847
+ }
848
+ try {
849
+ if (!this.db) {
850
+ throw new Error("Primary database client not initialized");
851
+ }
852
+ this.logger.debug(`Querying primary database for tenant: ${tenantIdentifier}`);
853
+ const schema = this.options.drizzleSchema;
854
+ const { tenants, tenantDatabaseConfigs } = schema;
855
+ const result = await this.db.select().from(tenants).leftJoin(tenantDatabaseConfigs, (0, import_drizzle_orm.eq)(tenants.id, tenantDatabaseConfigs.tenantId)).where((0, import_drizzle_orm.or)((0, import_drizzle_orm.eq)(tenants.id, tenantIdentifier), (0, import_drizzle_orm.eq)(tenants.subdomain, tenantIdentifier))).limit(1);
856
+ if (!result.length) {
857
+ this.logger.warn(`Tenant not found: ${tenantIdentifier}`);
858
+ return null;
859
+ }
860
+ const row = result[0];
861
+ const tenant = row.tenants;
862
+ const config = row.tenant_database_configs;
863
+ if (tenant.status !== "ACTIVE") {
864
+ this.logger.warn(`Tenant not active: ${tenantIdentifier}`);
865
+ return null;
866
+ }
867
+ const info = {
868
+ id: tenant.id,
869
+ subdomain: tenant.subdomain,
870
+ type: tenant.dbType,
871
+ status: tenant.status,
872
+ // For SHARED tenants: schema name
873
+ schemaName: config?.dbSchema || void 0,
874
+ // For DEDICATED tenants: database configuration from TenantDatabaseConfig table
875
+ databaseName: config?.dbName || void 0,
876
+ databaseHost: config?.dbHost || void 0,
877
+ databasePort: config?.dbPort || void 0,
878
+ databaseUsername: config?.dbUsername ? this.decrypt(config.dbUsername) : void 0,
879
+ databasePassword: config?.dbPassword ? this.decrypt(config.dbPassword) : void 0,
880
+ databaseSslMode: config?.dbSslMode || void 0,
881
+ connectionPoolSize: config?.connectionPoolSize || void 0
882
+ };
883
+ this.cacheInfo(info);
884
+ return info;
885
+ } catch (error) {
886
+ this.logger.error(`Failed to fetch tenant info: ${tenantIdentifier}`, error);
887
+ throw new import_common9.InternalServerErrorException("Failed to resolve tenant");
888
+ }
889
+ }
890
+ /**
891
+ * Cache tenant information with TTL
892
+ */
893
+ cacheInfo(info) {
894
+ this.tenantConfigCache.set(info.id, info);
895
+ this.tenantConfigCache.set(info.subdomain, info);
896
+ setTimeout(() => {
897
+ this.tenantConfigCache.delete(info.id);
898
+ this.tenantConfigCache.delete(info.subdomain);
899
+ this.logger.debug(`Cache expired for tenant: ${info.subdomain}`);
900
+ }, this.cacheTTL);
901
+ }
902
+ /**
903
+ * Clear cached tenant information
904
+ *
905
+ * Useful when tenant settings are updated and cache needs to be invalidated
906
+ *
907
+ * @param tenantIdentifier Tenant ID or subdomain
908
+ */
909
+ clearTenantCache(tenantIdentifier) {
910
+ const config = this.tenantConfigCache.get(tenantIdentifier);
911
+ if (config) {
912
+ this.tenantConfigCache.delete(config.id);
913
+ this.tenantConfigCache.delete(config.subdomain);
914
+ this.logger.log(`Cleared cache for tenant: ${tenantIdentifier}`);
915
+ }
916
+ }
917
+ /**
918
+ * Clear all cached tenant configurations
919
+ */
920
+ clearAllCaches() {
921
+ const size = this.tenantConfigCache.size;
922
+ this.tenantConfigCache.clear();
923
+ this.logger.log(`Cleared ${size} cached tenant configs`);
924
+ }
925
+ /**
926
+ * Get the Drizzle database instance for the primary database.
927
+ * This is a synchronous property that returns the initialized Drizzle client.
928
+ *
929
+ * @returns Primary database Drizzle instance
930
+ * @throws Error if primary database client is not initialized
931
+ */
932
+ get drizzleClient() {
933
+ if (!this.db) {
934
+ throw new Error("Primary database client not initialized");
935
+ }
936
+ return this.db;
937
+ }
938
+ /**
939
+ * Get the Drizzle schema
940
+ */
941
+ get schema() {
942
+ return this.options.drizzleSchema;
943
+ }
944
+ /**
945
+ * Decrypt database credentials
946
+ *
947
+ * Override this method to implement your encryption strategy
948
+ *
949
+ * @param encrypted Encrypted value
950
+ * @returns Decrypted value
951
+ */
952
+ decrypt(encrypted) {
953
+ return encrypted;
954
+ }
955
+ async onModuleDestroy() {
956
+ if (this.pool) {
957
+ await this.pool.end();
958
+ this.logger.log("Disconnected from primary database");
959
+ }
960
+ }
961
+ };
962
+ PrimaryDatabaseService2 = _ts_decorate7([
963
+ (0, import_common9.Injectable)(),
964
+ _ts_param2(0, (0, import_common9.Inject)(DATABASE_MODULE_OPTIONS)),
965
+ _ts_metadata5("design:type", Function),
966
+ _ts_metadata5("design:paramtypes", [
967
+ typeof DatabaseModuleOptions === "undefined" ? Object : DatabaseModuleOptions
968
+ ])
969
+ ], PrimaryDatabaseService2);
970
+
971
+ // src/database/services/tenant-context.service.ts
972
+ var import_common10 = require("@nestjs/common");
973
+ function _ts_decorate8(decorators, target, key, desc) {
974
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
975
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
976
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
977
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
978
+ }
979
+ __name(_ts_decorate8, "_ts_decorate");
980
+ var TenantContextService2 = class {
981
+ static {
982
+ __name(this, "TenantContextService");
983
+ }
984
+ tenantInfo = null;
985
+ /**
986
+ * Set tenant information for this request/message
987
+ *
988
+ * This is typically called by:
989
+ * - TenantContextInterceptor (for HTTP requests in gateway)
990
+ * - MessageTenantContextInterceptor (for RabbitMQ messages in microservices)
991
+ * - Manual context setup in message handlers
992
+ *
993
+ * @param tenantInfo Complete tenant information
994
+ * @throws Error if tenant context is already set (prevents accidental overwrites)
995
+ */
996
+ setTenant(tenantInfo) {
997
+ if (this.tenantInfo) {
998
+ throw new Error("Tenant context already set for this request");
999
+ }
1000
+ this.tenantInfo = tenantInfo;
1001
+ }
1002
+ /**
1003
+ * Get tenant information for this request/message
1004
+ *
1005
+ * @returns Tenant information
1006
+ * @throws UnauthorizedException if tenant context hasn't been set
1007
+ */
1008
+ getTenant() {
1009
+ if (!this.tenantInfo) {
1010
+ throw new import_common10.UnauthorizedException("Tenant context not set");
1011
+ }
1012
+ return this.tenantInfo;
1013
+ }
1014
+ /**
1015
+ * Check if tenant context has been set
1016
+ *
1017
+ * @returns true if tenant context is available
1018
+ */
1019
+ hasTenant() {
1020
+ return this.tenantInfo !== null;
798
1021
  }
799
1022
  /**
800
1023
  * Clear tenant context
@@ -825,213 +1048,58 @@ var TenantContextService = class {
825
1048
  return this.tenantInfo?.subdomain ?? null;
826
1049
  }
827
1050
  };
828
- TenantContextService = _ts_decorate6([
829
- (0, import_common6.Injectable)({
830
- scope: import_common6.Scope.REQUEST
1051
+ TenantContextService2 = _ts_decorate8([
1052
+ (0, import_common10.Injectable)({
1053
+ scope: import_common10.Scope.REQUEST
831
1054
  })
832
- ], TenantContextService);
1055
+ ], TenantContextService2);
833
1056
 
834
- // src/database/interceptors/message-tenant-context.interceptor.ts
835
- function _ts_decorate7(decorators, target, key, desc) {
1057
+ // src/database/services/tenant-database.service.ts
1058
+ var import_common11 = require("@nestjs/common");
1059
+ var import_node_postgres2 = require("drizzle-orm/node-postgres");
1060
+ var import_pg2 = require("pg");
1061
+ function _ts_decorate9(decorators, target, key, desc) {
836
1062
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
837
1063
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
838
1064
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
839
1065
  return c > 3 && r && Object.defineProperty(target, key, r), r;
840
1066
  }
841
- __name(_ts_decorate7, "_ts_decorate");
842
- function _ts_metadata4(k, v) {
1067
+ __name(_ts_decorate9, "_ts_decorate");
1068
+ function _ts_metadata6(k, v) {
843
1069
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
844
1070
  }
845
- __name(_ts_metadata4, "_ts_metadata");
846
- var MessageTenantContextInterceptor = class _MessageTenantContextInterceptor {
1071
+ __name(_ts_metadata6, "_ts_metadata");
1072
+ function _ts_param3(paramIndex, decorator) {
1073
+ return function(target, key) {
1074
+ decorator(target, key, paramIndex);
1075
+ };
1076
+ }
1077
+ __name(_ts_param3, "_ts_param");
1078
+ var TenantDatabaseService = class _TenantDatabaseService {
847
1079
  static {
848
- __name(this, "MessageTenantContextInterceptor");
1080
+ __name(this, "TenantDatabaseService");
849
1081
  }
1082
+ options;
850
1083
  tenantContext;
851
- logger = new import_common7.Logger(_MessageTenantContextInterceptor.name);
852
- constructor(tenantContext) {
1084
+ logger = new import_common11.Logger(_TenantDatabaseService.name);
1085
+ /** Connection pool: Map<cacheKey, TenantConnection> */
1086
+ clients = /* @__PURE__ */ new Map();
1087
+ /** Track last usage time for idle connection cleanup */
1088
+ clientLastUsed = /* @__PURE__ */ new Map();
1089
+ /** Cleanup interval timer */
1090
+ cleanupInterval;
1091
+ constructor(options, tenantContext) {
1092
+ this.options = options;
853
1093
  this.tenantContext = tenantContext;
854
- }
855
- intercept(context, next) {
856
- const contextType = context.getType();
857
- if (contextType === "rpc") {
858
- const rpcContext = context.switchToRpc();
859
- const payload = rpcContext.getData();
860
- if (payload && payload.tenant) {
861
- const tenant = payload.tenant;
862
- this.logger.debug(`Setting tenant context from message: ${tenant.subdomain}`);
863
- try {
864
- this.tenantContext.setTenant(tenant);
865
- this.logger.log(`Tenant context set: ${tenant.subdomain} (${tenant.type})`);
866
- } catch (error) {
867
- this.logger.error("Failed to set tenant context from message", error);
868
- }
869
- } else {
870
- this.logger.warn("Message payload missing tenant information");
871
- }
872
- }
873
- return next.handle().pipe((0, import_operators.tap)({
874
- next: /* @__PURE__ */ __name(() => {
875
- this.cleanupContext();
876
- }, "next"),
877
- error: /* @__PURE__ */ __name(() => {
878
- this.cleanupContext();
879
- }, "error"),
880
- complete: /* @__PURE__ */ __name(() => {
881
- this.cleanupContext();
882
- }, "complete")
883
- }));
1094
+ this.startConnectionCleaner();
884
1095
  }
885
1096
  /**
886
- * Clean up tenant context after message is processed
887
- */
888
- cleanupContext() {
889
- if (this.tenantContext.hasTenant()) {
890
- const tenant = this.tenantContext.getTenantIdSafe();
891
- this.tenantContext.clearTenant();
892
- this.logger.debug(`Cleaned up tenant context: ${tenant}`);
893
- }
894
- }
895
- };
896
- MessageTenantContextInterceptor = _ts_decorate7([
897
- (0, import_common7.Injectable)({
898
- scope: import_common7.Scope.REQUEST
899
- }),
900
- _ts_metadata4("design:type", Function),
901
- _ts_metadata4("design:paramtypes", [
902
- typeof TenantContextService === "undefined" ? Object : TenantContextService
903
- ])
904
- ], MessageTenantContextInterceptor);
905
-
906
- // src/database/interceptors/tenant-context.interceptor.ts
907
- var import_common8 = require("@nestjs/common");
908
- var import_core4 = require("@nestjs/core");
909
- function _ts_decorate8(decorators, target, key, desc) {
910
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
911
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
912
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
913
- return c > 3 && r && Object.defineProperty(target, key, r), r;
914
- }
915
- __name(_ts_decorate8, "_ts_decorate");
916
- function _ts_metadata5(k, v) {
917
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
918
- }
919
- __name(_ts_metadata5, "_ts_metadata");
920
- var TenantContextInterceptor = class _TenantContextInterceptor {
921
- static {
922
- __name(this, "TenantContextInterceptor");
923
- }
924
- reflector;
925
- tenantContext;
926
- primaryDatabase;
927
- requestService;
928
- logger = new import_common8.Logger(_TenantContextInterceptor.name);
929
- constructor(reflector, tenantContext, primaryDatabase, requestService) {
930
- this.reflector = reflector;
931
- this.tenantContext = tenantContext;
932
- this.primaryDatabase = primaryDatabase;
933
- this.requestService = requestService;
934
- }
935
- async intercept(context, next) {
936
- const request = context.switchToHttp().getRequest();
937
- this.logger.debug(`Processing request: ${request.method} ${request.url}`);
938
- const isPublic = this.reflector.getAllAndOverride("isPublic", [
939
- context.getHandler(),
940
- context.getClass()
941
- ]);
942
- try {
943
- const tenantIdentifier = this.requestService.getTenantIdentifier();
944
- if (isPublic && !tenantIdentifier) {
945
- this.logger.debug("Public endpoint without tenant identifier, skipping tenant context setup");
946
- return next.handle();
947
- }
948
- if (!tenantIdentifier) {
949
- throw new import_common8.UnauthorizedException("Tenant identifier not found in request");
950
- }
951
- this.logger.debug(`Tenant identifier extracted: ${tenantIdentifier}`);
952
- if (tenantIdentifier === "cloud") {
953
- this.logger.log("Cloud platform access detected, skipping tenant context setup");
954
- return next.handle();
955
- }
956
- const tenantInfo = await this.primaryDatabase.getTenantInfo(tenantIdentifier);
957
- if (!tenantInfo) {
958
- this.logger.warn(`Invalid tenant: ${tenantIdentifier}`);
959
- throw new import_common8.UnauthorizedException("Invalid tenant");
960
- }
961
- if (tenantInfo.status !== "ACTIVE") {
962
- this.logger.warn(`Tenant ${tenantIdentifier} has status: ${tenantInfo.status}`);
963
- throw new import_common8.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
964
- }
965
- this.logger.debug(`Tenant config loaded: ${tenantInfo.subdomain} (${tenantInfo.type})`);
966
- this.tenantContext.setTenant(tenantInfo);
967
- request.tenant = tenantInfo;
968
- this.logger.log(`Tenant context set: ${tenantInfo.subdomain}`);
969
- } catch (error) {
970
- this.logger.error("Failed to set tenant context", error);
971
- throw error;
972
- }
973
- return next.handle();
974
- }
975
- };
976
- TenantContextInterceptor = _ts_decorate8([
977
- (0, import_common8.Injectable)({
978
- scope: import_common8.Scope.REQUEST
979
- }),
980
- _ts_metadata5("design:type", Function),
981
- _ts_metadata5("design:paramtypes", [
982
- typeof import_core4.Reflector === "undefined" ? Object : import_core4.Reflector,
983
- typeof TenantContextService === "undefined" ? Object : TenantContextService,
984
- typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
985
- typeof RequestService === "undefined" ? Object : RequestService
986
- ])
987
- ], TenantContextInterceptor);
988
-
989
- // src/database/services/tenant-database.service.ts
990
- var import_common9 = require("@nestjs/common");
991
- var import_pg2 = require("pg");
992
- var import_node_postgres2 = require("drizzle-orm/node-postgres");
993
- function _ts_decorate9(decorators, target, key, desc) {
994
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
995
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
996
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
997
- return c > 3 && r && Object.defineProperty(target, key, r), r;
998
- }
999
- __name(_ts_decorate9, "_ts_decorate");
1000
- function _ts_metadata6(k, v) {
1001
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1002
- }
1003
- __name(_ts_metadata6, "_ts_metadata");
1004
- function _ts_param3(paramIndex, decorator) {
1005
- return function(target, key) {
1006
- decorator(target, key, paramIndex);
1007
- };
1008
- }
1009
- __name(_ts_param3, "_ts_param");
1010
- var TenantDatabaseService = class _TenantDatabaseService {
1011
- static {
1012
- __name(this, "TenantDatabaseService");
1013
- }
1014
- options;
1015
- tenantContext;
1016
- logger = new import_common9.Logger(_TenantDatabaseService.name);
1017
- /** Connection pool: Map<cacheKey, TenantConnection> */
1018
- clients = /* @__PURE__ */ new Map();
1019
- /** Track last usage time for idle connection cleanup */
1020
- clientLastUsed = /* @__PURE__ */ new Map();
1021
- /** Cleanup interval timer */
1022
- cleanupInterval;
1023
- constructor(options, tenantContext) {
1024
- this.options = options;
1025
- this.tenantContext = tenantContext;
1026
- this.startConnectionCleaner();
1027
- }
1028
- /**
1029
- * Get the Drizzle client for the current tenant's database.
1030
- * This returns the tenant-scoped database client.
1031
- *
1032
- * @returns Tenant-scoped Drizzle database instance
1033
- * @throws UnauthorizedException if tenant context not set
1034
- * @throws InternalServerErrorException if connection fails
1097
+ * Get the Drizzle client for the current tenant's database.
1098
+ * This returns the tenant-scoped database client.
1099
+ *
1100
+ * @returns Tenant-scoped Drizzle database instance
1101
+ * @throws UnauthorizedException if tenant context not set
1102
+ * @throws InternalServerErrorException if connection fails
1035
1103
  */
1036
1104
  get drizzleClient() {
1037
1105
  return this.getDbClient();
@@ -1090,7 +1158,7 @@ var TenantDatabaseService = class _TenantDatabaseService {
1090
1158
  };
1091
1159
  } catch (error) {
1092
1160
  this.logger.error(`Failed to create database connection for tenant: ${tenant.subdomain}`, error);
1093
- throw new import_common9.InternalServerErrorException("Failed to connect to tenant database");
1161
+ throw new import_common11.InternalServerErrorException("Failed to connect to tenant database");
1094
1162
  }
1095
1163
  }
1096
1164
  /**
@@ -1183,8 +1251,8 @@ var TenantDatabaseService = class _TenantDatabaseService {
1183
1251
  }
1184
1252
  };
1185
1253
  TenantDatabaseService = _ts_decorate9([
1186
- (0, import_common9.Injectable)(),
1187
- _ts_param3(0, (0, import_common9.Inject)(DATABASE_MODULE_OPTIONS)),
1254
+ (0, import_common11.Injectable)(),
1255
+ _ts_param3(0, (0, import_common11.Inject)(DATABASE_MODULE_OPTIONS)),
1188
1256
  _ts_metadata6("design:type", Function),
1189
1257
  _ts_metadata6("design:paramtypes", [
1190
1258
  typeof DatabaseModuleOptions === "undefined" ? Object : DatabaseModuleOptions,
@@ -1232,7 +1300,7 @@ var DatabaseModule = class _DatabaseModule {
1232
1300
  * })
1233
1301
  */
1234
1302
  static forServer(options) {
1235
- return this.createDynamicModule(options, "server");
1303
+ return _DatabaseModule.createDynamicModule(options, "server");
1236
1304
  }
1237
1305
  /**
1238
1306
  * Configure DatabaseModule for Microservice/Messaging mode (RabbitMQ workers)
@@ -1254,7 +1322,7 @@ var DatabaseModule = class _DatabaseModule {
1254
1322
  * })
1255
1323
  */
1256
1324
  static forMicroservice(options) {
1257
- return this.createDynamicModule(options, "microservice");
1325
+ return _DatabaseModule.createDynamicModule(options, "microservice");
1258
1326
  }
1259
1327
  /**
1260
1328
  * Internal helper to create dynamic module with conditional interceptor registration
@@ -1271,18 +1339,18 @@ var DatabaseModule = class _DatabaseModule {
1271
1339
  };
1272
1340
  const providers = [
1273
1341
  asyncProvider,
1274
- TenantContextService,
1275
- PrimaryDatabaseService,
1342
+ TenantContextService2,
1343
+ PrimaryDatabaseService2,
1276
1344
  TenantDatabaseService
1277
1345
  ];
1278
1346
  if (mode === "server") {
1279
1347
  providers.push({
1280
- provide: import_core5.APP_INTERCEPTOR,
1348
+ provide: import_core3.APP_INTERCEPTOR,
1281
1349
  useClass: TenantContextInterceptor
1282
1350
  });
1283
1351
  } else {
1284
1352
  providers.push({
1285
- provide: import_core5.APP_INTERCEPTOR,
1353
+ provide: import_core3.APP_INTERCEPTOR,
1286
1354
  useClass: MessageTenantContextInterceptor
1287
1355
  });
1288
1356
  }
@@ -1294,21 +1362,36 @@ var DatabaseModule = class _DatabaseModule {
1294
1362
  providers,
1295
1363
  exports: [
1296
1364
  TenantDatabaseService,
1297
- TenantContextService,
1298
- PrimaryDatabaseService,
1365
+ TenantContextService2,
1366
+ PrimaryDatabaseService2,
1299
1367
  asyncProvider
1300
1368
  ]
1301
1369
  };
1302
1370
  }
1303
1371
  };
1304
1372
  DatabaseModule = _ts_decorate10([
1305
- (0, import_common10.Global)(),
1306
- (0, import_common10.Module)({})
1373
+ (0, import_common12.Global)(),
1374
+ (0, import_common12.Module)({})
1307
1375
  ], DatabaseModule);
1308
1376
 
1377
+ // src/database/decorators/tenant.decorator.ts
1378
+ var import_common13 = require("@nestjs/common");
1379
+ var Tenant = (0, import_common13.createParamDecorator)((_data, ctx) => {
1380
+ const request = ctx.switchToHttp().getRequest();
1381
+ const tenantContext = request.app?.get?.(TenantContextService2);
1382
+ if (!tenantContext) {
1383
+ throw new Error("TenantContextService not found.");
1384
+ }
1385
+ return tenantContext.getTenant();
1386
+ });
1387
+
1309
1388
  // src/database/repositories/primary-base.repository.ts
1310
- var import_common11 = require("@nestjs/common");
1389
+ var import_common14 = require("@nestjs/common");
1311
1390
  var import_drizzle_orm2 = require("drizzle-orm");
1391
+ function snakeToCamel(str) {
1392
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
1393
+ }
1394
+ __name(snakeToCamel, "snakeToCamel");
1312
1395
  var PrimaryBaseRepository = class {
1313
1396
  static {
1314
1397
  __name(this, "PrimaryBaseRepository");
@@ -1318,7 +1401,8 @@ var PrimaryBaseRepository = class {
1318
1401
  logger;
1319
1402
  /**
1320
1403
  * The table name extracted from the Drizzle table at runtime.
1321
- * Used to access the query API for this repository's table.
1404
+ * Stored in camelCase to match Drizzle's query object keys.
1405
+ * Example: 'email_verifications' -> 'emailVerifications'
1322
1406
  */
1323
1407
  tableName;
1324
1408
  /**
@@ -1371,10 +1455,11 @@ var PrimaryBaseRepository = class {
1371
1455
  constructor(database, table) {
1372
1456
  this.database = database;
1373
1457
  this.table = table;
1374
- this.tableName = (0, import_drizzle_orm2.getTableName)(table);
1375
- this.logger = new import_common11.Logger(this.constructor.name);
1458
+ const dbTableName = (0, import_drizzle_orm2.getTableName)(table);
1459
+ this.tableName = snakeToCamel(dbTableName);
1460
+ this.logger = new import_common14.Logger(this.constructor.name);
1376
1461
  this.logger.debug(`Initialized ${this.constructor.name}`);
1377
- this.logger.debug(`Table name from getTableName: '${this.tableName}'`);
1462
+ this.logger.debug(`Table name: '${dbTableName}' -> query key: '${this.tableName}'`);
1378
1463
  }
1379
1464
  /**
1380
1465
  * Create a new record
@@ -1612,7 +1697,7 @@ var PrimaryBaseRepository = class {
1612
1697
  };
1613
1698
 
1614
1699
  // src/database/repositories/tenant-base.repository.ts
1615
- var import_common12 = require("@nestjs/common");
1700
+ var import_common15 = require("@nestjs/common");
1616
1701
  var import_drizzle_orm3 = require("drizzle-orm");
1617
1702
  var TenantBaseRepository = class {
1618
1703
  static {
@@ -1669,7 +1754,7 @@ var TenantBaseRepository = class {
1669
1754
  this.database = database;
1670
1755
  this.table = table;
1671
1756
  this.tableName = (0, import_drizzle_orm3.getTableName)(table);
1672
- this.logger = new import_common12.Logger(this.constructor.name);
1757
+ this.logger = new import_common15.Logger(this.constructor.name);
1673
1758
  this.logger.debug(`Initialized ${this.constructor.name}`);
1674
1759
  }
1675
1760
  /**
@@ -1901,424 +1986,282 @@ var TenantBaseRepository = class {
1901
1986
  }
1902
1987
  };
1903
1988
 
1904
- // src/database/decorators/tenant.decorator.ts
1905
- var import_common13 = require("@nestjs/common");
1906
- var Tenant = (0, import_common13.createParamDecorator)((data, ctx) => {
1907
- const request = ctx.switchToHttp().getRequest();
1908
- const tenantContext = request.app?.get?.(TenantContextService);
1909
- if (!tenantContext) {
1910
- throw new Error("TenantContextService not found.");
1911
- }
1912
- return tenantContext.getTenant();
1913
- });
1914
-
1915
- // src/auth/decorators/onboarding.decorator.ts
1916
- var import_common14 = require("@nestjs/common");
1917
- var Onboarding = /* @__PURE__ */ __name(() => (0, import_common14.SetMetadata)("isOnboarding", true), "Onboarding");
1918
-
1919
- // src/auth/decorators/public.decorator.ts
1920
- var import_common15 = require("@nestjs/common");
1921
- var Public = /* @__PURE__ */ __name(() => (0, import_common15.SetMetadata)("isPublic", true), "Public");
1922
-
1923
- // src/http/http.module.ts
1989
+ // src/exceptions/bad-gateway.exception.ts
1924
1990
  var import_common17 = require("@nestjs/common");
1925
1991
 
1926
- // src/http/guards/csrf.guard.ts
1992
+ // src/exceptions/base-field.exception.ts
1927
1993
  var import_common16 = require("@nestjs/common");
1928
- var import_core6 = require("@nestjs/core");
1929
- function _ts_decorate11(decorators, target, key, desc) {
1930
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1931
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1932
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1933
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1934
- }
1935
- __name(_ts_decorate11, "_ts_decorate");
1936
- function _ts_metadata7(k, v) {
1937
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1938
- }
1939
- __name(_ts_metadata7, "_ts_metadata");
1940
- var CsrfGuard = class _CsrfGuard {
1994
+ var BaseFieldException = class extends import_common16.HttpException {
1941
1995
  static {
1942
- __name(this, "CsrfGuard");
1996
+ __name(this, "BaseFieldException");
1943
1997
  }
1944
- reflector;
1945
- logger = new import_common16.Logger(_CsrfGuard.name);
1946
- constructor(reflector) {
1947
- this.reflector = reflector;
1998
+ constructor(statusOrMessageOrErrors, messageOrStatus, statusOrDetail, detail) {
1999
+ let errors;
2000
+ let httpStatus;
2001
+ let finalDetail;
2002
+ if (Array.isArray(statusOrMessageOrErrors)) {
2003
+ errors = statusOrMessageOrErrors;
2004
+ httpStatus = messageOrStatus || import_common16.HttpStatus.BAD_REQUEST;
2005
+ finalDetail = typeof statusOrDetail === "string" ? statusOrDetail : void 0;
2006
+ } else if (typeof statusOrMessageOrErrors === "string" && typeof messageOrStatus === "string") {
2007
+ errors = [
2008
+ {
2009
+ field: statusOrMessageOrErrors,
2010
+ message: messageOrStatus
2011
+ }
2012
+ ];
2013
+ httpStatus = statusOrDetail;
2014
+ finalDetail = detail;
2015
+ } else if (typeof statusOrMessageOrErrors === "string") {
2016
+ errors = [
2017
+ {
2018
+ message: statusOrMessageOrErrors
2019
+ }
2020
+ ];
2021
+ httpStatus = messageOrStatus;
2022
+ finalDetail = typeof statusOrDetail === "string" ? statusOrDetail : void 0;
2023
+ } else {
2024
+ errors = [
2025
+ {
2026
+ message: "An error occurred"
2027
+ }
2028
+ ];
2029
+ httpStatus = statusOrMessageOrErrors;
2030
+ finalDetail = void 0;
2031
+ }
2032
+ const response = finalDetail !== void 0 ? {
2033
+ errors,
2034
+ detail: finalDetail
2035
+ } : {
2036
+ errors
2037
+ };
2038
+ super(response, httpStatus);
1948
2039
  }
1949
- async canActivate(context) {
1950
- const request = context.switchToHttp().getRequest();
1951
- const reply = context.switchToHttp().getResponse();
1952
- const safeMethods = [
1953
- "GET",
1954
- "HEAD",
1955
- "OPTIONS"
1956
- ];
1957
- if (safeMethods.includes(request.method)) {
1958
- return true;
2040
+ };
2041
+
2042
+ // src/exceptions/bad-gateway.exception.ts
2043
+ var BadGatewayException = class extends BaseFieldException {
2044
+ static {
2045
+ __name(this, "BadGatewayException");
2046
+ }
2047
+ constructor(messageOrField, fieldMessageOrDetail, detail) {
2048
+ if (Array.isArray(messageOrField)) {
2049
+ super(messageOrField, import_common17.HttpStatus.BAD_GATEWAY, fieldMessageOrDetail);
2050
+ } else if (detail !== void 0) {
2051
+ super(messageOrField, fieldMessageOrDetail, import_common17.HttpStatus.BAD_GATEWAY, detail);
2052
+ } else if (fieldMessageOrDetail) {
2053
+ super(messageOrField, fieldMessageOrDetail, import_common17.HttpStatus.BAD_GATEWAY);
2054
+ } else {
2055
+ super(messageOrField, import_common17.HttpStatus.BAD_GATEWAY);
1959
2056
  }
1960
- try {
1961
- const fastifyInstance = request.server;
1962
- if (!fastifyInstance.csrfProtection) {
1963
- this.logger.error("CSRF protection plugin not found. Ensure @fastify/csrf-protection is registered.");
1964
- throw new import_common16.ForbiddenException("CSRF protection not configured");
1965
- }
1966
- await new Promise((resolve, reject) => {
1967
- fastifyInstance.csrfProtection(request, reply, (err) => {
1968
- if (err) {
1969
- reject(err);
1970
- } else {
1971
- resolve();
1972
- }
1973
- });
1974
- });
1975
- this.logger.debug(`CSRF validation successful for ${request.method} ${request.url}`);
1976
- return true;
1977
- } catch (error) {
1978
- this.logger.warn(`CSRF validation failed for ${request.method} ${request.url}: ${error instanceof Error ? error.message : "Unknown error"}`);
1979
- throw new import_common16.ForbiddenException({
1980
- errors: [
1981
- {
1982
- field: "csrf",
1983
- message: "Invalid or missing CSRF token"
1984
- }
1985
- ],
1986
- message: "CSRF validation failed"
1987
- });
1988
- }
1989
- }
1990
- };
1991
- CsrfGuard = _ts_decorate11([
1992
- (0, import_common16.Injectable)(),
1993
- _ts_metadata7("design:type", Function),
1994
- _ts_metadata7("design:paramtypes", [
1995
- typeof import_core6.Reflector === "undefined" ? Object : import_core6.Reflector
1996
- ])
1997
- ], CsrfGuard);
1998
-
1999
- // src/http/http.module.ts
2000
- function _ts_decorate12(decorators, target, key, desc) {
2001
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2002
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2003
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2004
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2005
- }
2006
- __name(_ts_decorate12, "_ts_decorate");
2007
- var HttpModule = class {
2008
- static {
2009
- __name(this, "HttpModule");
2010
2057
  }
2011
2058
  };
2012
- HttpModule = _ts_decorate12([
2013
- (0, import_common17.Module)({
2014
- providers: [
2015
- CsrfGuard
2016
- ],
2017
- exports: [
2018
- CsrfGuard
2019
- ]
2020
- })
2021
- ], HttpModule);
2022
2059
 
2023
- // src/filters/http-exception.filter.ts
2060
+ // src/exceptions/bad-request.exception.ts
2024
2061
  var import_common18 = require("@nestjs/common");
2025
- function _ts_decorate13(decorators, target, key, desc) {
2026
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2027
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2028
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2029
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2030
- }
2031
- __name(_ts_decorate13, "_ts_decorate");
2032
- function getHttpStatusTitle(status) {
2033
- const enumKey = Object.entries(import_common18.HttpStatus).find(([key, value]) => value === status && isNaN(Number(key)))?.[0];
2034
- if (!enumKey) {
2035
- return "Error";
2036
- }
2037
- return enumKey.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
2038
- }
2039
- __name(getHttpStatusTitle, "getHttpStatusTitle");
2040
- var HttpExceptionFilter = class _HttpExceptionFilter {
2062
+ var BadRequestException = class extends BaseFieldException {
2041
2063
  static {
2042
- __name(this, "HttpExceptionFilter");
2064
+ __name(this, "BadRequestException");
2043
2065
  }
2044
- logger = new import_common18.Logger(_HttpExceptionFilter.name);
2045
- catch(exception, host) {
2046
- const ctx = host.switchToHttp();
2047
- const response = ctx.getResponse();
2048
- let status = import_common18.HttpStatus.INTERNAL_SERVER_ERROR;
2049
- let errors = [];
2050
- let detail = "Internal server error";
2051
- if (exception instanceof import_common18.HttpException) {
2052
- status = exception.getStatus();
2053
- const exceptionResponse = exception.getResponse();
2054
- if (typeof exceptionResponse === "object" && exceptionResponse !== null) {
2055
- const responseObj = exceptionResponse;
2056
- if ("errors" in responseObj && Array.isArray(responseObj.errors)) {
2057
- errors = responseObj.errors;
2058
- detail = ("detail" in responseObj ? responseObj.detail : void 0) || exception.message;
2059
- } else if ("message" in responseObj && Array.isArray(responseObj.message)) {
2060
- errors = responseObj.message.map((msg) => {
2061
- if (typeof msg === "object" && "property" in msg && "constraints" in msg) {
2062
- const constraintValues = Object.values(msg.constraints);
2063
- return {
2064
- field: msg.property,
2065
- message: constraintValues[0] ?? "Validation failed"
2066
- };
2067
- }
2068
- return {
2069
- message: typeof msg === "string" ? msg : JSON.stringify(msg)
2070
- };
2071
- });
2072
- detail = "Validation failed";
2073
- } else if ("message" in responseObj) {
2074
- const message = responseObj.message;
2075
- errors = [
2076
- {
2077
- message: Array.isArray(message) ? message.join(", ") : message
2078
- }
2079
- ];
2080
- detail = ("error" in responseObj ? responseObj.error : void 0) || exception.message;
2081
- }
2082
- } else if (typeof exceptionResponse === "string") {
2083
- errors = [
2084
- {
2085
- message: exceptionResponse
2086
- }
2087
- ];
2088
- detail = exceptionResponse;
2089
- }
2066
+ constructor(messageOrField, fieldMessageOrDetail, detail) {
2067
+ if (Array.isArray(messageOrField)) {
2068
+ super(messageOrField, import_common18.HttpStatus.BAD_REQUEST, fieldMessageOrDetail);
2069
+ } else if (detail !== void 0) {
2070
+ super(messageOrField, fieldMessageOrDetail, import_common18.HttpStatus.BAD_REQUEST, detail);
2071
+ } else if (fieldMessageOrDetail) {
2072
+ super(messageOrField, fieldMessageOrDetail, import_common18.HttpStatus.BAD_REQUEST);
2090
2073
  } else {
2091
- const errorMessage = exception instanceof Error ? exception.message : "Unknown error";
2092
- const stack = exception instanceof Error ? exception.stack : void 0;
2093
- this.logger.error(`Unexpected error: ${errorMessage}`, stack);
2094
- errors = [
2095
- {
2096
- message: "An unexpected error occurred"
2097
- }
2098
- ];
2074
+ super(messageOrField, import_common18.HttpStatus.BAD_REQUEST);
2099
2075
  }
2100
- const problemDetails = {
2101
- title: getHttpStatusTitle(status),
2102
- status,
2103
- detail,
2104
- errors
2105
- };
2106
- response.status(status).send(problemDetails);
2107
2076
  }
2108
2077
  };
2109
- HttpExceptionFilter = _ts_decorate13([
2110
- (0, import_common18.Catch)()
2111
- ], HttpExceptionFilter);
2112
2078
 
2113
- // src/exceptions/base-field.exception.ts
2079
+ // src/exceptions/conflict.exception.ts
2114
2080
  var import_common19 = require("@nestjs/common");
2115
- var BaseFieldException = class extends import_common19.HttpException {
2081
+ var ConflictException = class extends BaseFieldException {
2116
2082
  static {
2117
- __name(this, "BaseFieldException");
2083
+ __name(this, "ConflictException");
2118
2084
  }
2119
- constructor(statusOrMessageOrErrors, messageOrStatus, statusOrDetail, detail) {
2120
- let errors;
2121
- let httpStatus;
2122
- let finalDetail;
2123
- if (Array.isArray(statusOrMessageOrErrors)) {
2124
- errors = statusOrMessageOrErrors;
2125
- httpStatus = messageOrStatus || import_common19.HttpStatus.BAD_REQUEST;
2126
- finalDetail = typeof statusOrDetail === "string" ? statusOrDetail : void 0;
2127
- } else if (typeof statusOrMessageOrErrors === "string" && typeof messageOrStatus === "string") {
2128
- errors = [
2129
- {
2130
- field: statusOrMessageOrErrors,
2131
- message: messageOrStatus
2132
- }
2133
- ];
2134
- httpStatus = statusOrDetail;
2135
- finalDetail = detail;
2136
- } else if (typeof statusOrMessageOrErrors === "string") {
2137
- errors = [
2138
- {
2139
- message: statusOrMessageOrErrors
2140
- }
2141
- ];
2142
- httpStatus = messageOrStatus;
2143
- finalDetail = typeof statusOrDetail === "string" ? statusOrDetail : void 0;
2085
+ constructor(messageOrField, fieldMessageOrDetail, detail) {
2086
+ if (Array.isArray(messageOrField)) {
2087
+ super(messageOrField, import_common19.HttpStatus.CONFLICT, fieldMessageOrDetail);
2088
+ } else if (detail !== void 0) {
2089
+ super(messageOrField, fieldMessageOrDetail, import_common19.HttpStatus.CONFLICT, detail);
2090
+ } else if (fieldMessageOrDetail) {
2091
+ super(messageOrField, fieldMessageOrDetail, import_common19.HttpStatus.CONFLICT);
2144
2092
  } else {
2145
- errors = [
2146
- {
2147
- message: "An error occurred"
2148
- }
2149
- ];
2150
- httpStatus = statusOrMessageOrErrors;
2151
- finalDetail = void 0;
2093
+ super(messageOrField, import_common19.HttpStatus.CONFLICT);
2152
2094
  }
2153
- const response = finalDetail !== void 0 ? {
2154
- errors,
2155
- detail: finalDetail
2156
- } : {
2157
- errors
2158
- };
2159
- super(response, httpStatus);
2160
2095
  }
2161
2096
  };
2162
2097
 
2163
- // src/exceptions/bad-request.exception.ts
2098
+ // src/exceptions/forbidden.exception.ts
2164
2099
  var import_common20 = require("@nestjs/common");
2165
- var BadRequestException = class extends BaseFieldException {
2100
+ var ForbiddenException = class extends BaseFieldException {
2166
2101
  static {
2167
- __name(this, "BadRequestException");
2102
+ __name(this, "ForbiddenException");
2168
2103
  }
2169
2104
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2170
2105
  if (Array.isArray(messageOrField)) {
2171
- super(messageOrField, import_common20.HttpStatus.BAD_REQUEST, fieldMessageOrDetail);
2106
+ super(messageOrField, import_common20.HttpStatus.FORBIDDEN, fieldMessageOrDetail);
2172
2107
  } else if (detail !== void 0) {
2173
- super(messageOrField, fieldMessageOrDetail, import_common20.HttpStatus.BAD_REQUEST, detail);
2108
+ super(messageOrField, fieldMessageOrDetail, import_common20.HttpStatus.FORBIDDEN, detail);
2174
2109
  } else if (fieldMessageOrDetail) {
2175
- super(messageOrField, fieldMessageOrDetail, import_common20.HttpStatus.BAD_REQUEST);
2110
+ super(messageOrField, fieldMessageOrDetail, import_common20.HttpStatus.FORBIDDEN);
2176
2111
  } else {
2177
- super(messageOrField, import_common20.HttpStatus.BAD_REQUEST);
2112
+ super(messageOrField, import_common20.HttpStatus.FORBIDDEN);
2178
2113
  }
2179
2114
  }
2180
2115
  };
2181
2116
 
2182
- // src/exceptions/unauthorized.exception.ts
2117
+ // src/exceptions/gone.exception.ts
2183
2118
  var import_common21 = require("@nestjs/common");
2184
- var UnauthorizedException4 = class extends BaseFieldException {
2119
+ var GoneException = class extends BaseFieldException {
2185
2120
  static {
2186
- __name(this, "UnauthorizedException");
2121
+ __name(this, "GoneException");
2187
2122
  }
2188
2123
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2189
2124
  if (Array.isArray(messageOrField)) {
2190
- super(messageOrField, import_common21.HttpStatus.UNAUTHORIZED, fieldMessageOrDetail);
2125
+ super(messageOrField, import_common21.HttpStatus.GONE, fieldMessageOrDetail);
2191
2126
  } else if (detail !== void 0) {
2192
- super(messageOrField, fieldMessageOrDetail, import_common21.HttpStatus.UNAUTHORIZED, detail);
2127
+ super(messageOrField, fieldMessageOrDetail, import_common21.HttpStatus.GONE, detail);
2193
2128
  } else if (fieldMessageOrDetail) {
2194
- super(messageOrField, fieldMessageOrDetail, import_common21.HttpStatus.UNAUTHORIZED);
2129
+ super(messageOrField, fieldMessageOrDetail, import_common21.HttpStatus.GONE);
2195
2130
  } else {
2196
- super(messageOrField, import_common21.HttpStatus.UNAUTHORIZED);
2131
+ super(messageOrField, import_common21.HttpStatus.GONE);
2197
2132
  }
2198
2133
  }
2199
2134
  };
2200
2135
 
2201
- // src/exceptions/forbidden.exception.ts
2136
+ // src/exceptions/internal-server-error.exception.ts
2202
2137
  var import_common22 = require("@nestjs/common");
2203
- var ForbiddenException2 = class extends BaseFieldException {
2138
+ var InternalServerErrorException3 = class extends BaseFieldException {
2204
2139
  static {
2205
- __name(this, "ForbiddenException");
2140
+ __name(this, "InternalServerErrorException");
2206
2141
  }
2207
2142
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2208
2143
  if (Array.isArray(messageOrField)) {
2209
- super(messageOrField, import_common22.HttpStatus.FORBIDDEN, fieldMessageOrDetail);
2144
+ super(messageOrField, import_common22.HttpStatus.INTERNAL_SERVER_ERROR, fieldMessageOrDetail);
2210
2145
  } else if (detail !== void 0) {
2211
- super(messageOrField, fieldMessageOrDetail, import_common22.HttpStatus.FORBIDDEN, detail);
2146
+ super(messageOrField, fieldMessageOrDetail, import_common22.HttpStatus.INTERNAL_SERVER_ERROR, detail);
2212
2147
  } else if (fieldMessageOrDetail) {
2213
- super(messageOrField, fieldMessageOrDetail, import_common22.HttpStatus.FORBIDDEN);
2148
+ super(messageOrField, fieldMessageOrDetail, import_common22.HttpStatus.INTERNAL_SERVER_ERROR);
2214
2149
  } else {
2215
- super(messageOrField, import_common22.HttpStatus.FORBIDDEN);
2150
+ super(messageOrField, import_common22.HttpStatus.INTERNAL_SERVER_ERROR);
2216
2151
  }
2217
2152
  }
2218
2153
  };
2219
2154
 
2220
- // src/exceptions/not-found.exception.ts
2155
+ // src/exceptions/method-not-allowed.exception.ts
2221
2156
  var import_common23 = require("@nestjs/common");
2222
- var NotFoundException = class extends BaseFieldException {
2157
+ var MethodNotAllowedException = class extends BaseFieldException {
2223
2158
  static {
2224
- __name(this, "NotFoundException");
2159
+ __name(this, "MethodNotAllowedException");
2225
2160
  }
2226
2161
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2227
2162
  if (Array.isArray(messageOrField)) {
2228
- super(messageOrField, import_common23.HttpStatus.NOT_FOUND, fieldMessageOrDetail);
2163
+ super(messageOrField, import_common23.HttpStatus.METHOD_NOT_ALLOWED, fieldMessageOrDetail);
2229
2164
  } else if (detail !== void 0) {
2230
- super(messageOrField, fieldMessageOrDetail, import_common23.HttpStatus.NOT_FOUND, detail);
2165
+ super(messageOrField, fieldMessageOrDetail, import_common23.HttpStatus.METHOD_NOT_ALLOWED, detail);
2231
2166
  } else if (fieldMessageOrDetail) {
2232
- super(messageOrField, fieldMessageOrDetail, import_common23.HttpStatus.NOT_FOUND);
2167
+ super(messageOrField, fieldMessageOrDetail, import_common23.HttpStatus.METHOD_NOT_ALLOWED);
2233
2168
  } else {
2234
- super(messageOrField, import_common23.HttpStatus.NOT_FOUND);
2169
+ super(messageOrField, import_common23.HttpStatus.METHOD_NOT_ALLOWED);
2235
2170
  }
2236
2171
  }
2237
2172
  };
2238
2173
 
2239
- // src/exceptions/conflict.exception.ts
2174
+ // src/exceptions/not-acceptable.exception.ts
2240
2175
  var import_common24 = require("@nestjs/common");
2241
- var ConflictException = class extends BaseFieldException {
2176
+ var NotAcceptableException = class extends BaseFieldException {
2242
2177
  static {
2243
- __name(this, "ConflictException");
2178
+ __name(this, "NotAcceptableException");
2244
2179
  }
2245
2180
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2246
2181
  if (Array.isArray(messageOrField)) {
2247
- super(messageOrField, import_common24.HttpStatus.CONFLICT, fieldMessageOrDetail);
2182
+ super(messageOrField, import_common24.HttpStatus.NOT_ACCEPTABLE, fieldMessageOrDetail);
2248
2183
  } else if (detail !== void 0) {
2249
- super(messageOrField, fieldMessageOrDetail, import_common24.HttpStatus.CONFLICT, detail);
2184
+ super(messageOrField, fieldMessageOrDetail, import_common24.HttpStatus.NOT_ACCEPTABLE, detail);
2250
2185
  } else if (fieldMessageOrDetail) {
2251
- super(messageOrField, fieldMessageOrDetail, import_common24.HttpStatus.CONFLICT);
2186
+ super(messageOrField, fieldMessageOrDetail, import_common24.HttpStatus.NOT_ACCEPTABLE);
2252
2187
  } else {
2253
- super(messageOrField, import_common24.HttpStatus.CONFLICT);
2188
+ super(messageOrField, import_common24.HttpStatus.NOT_ACCEPTABLE);
2254
2189
  }
2255
2190
  }
2256
2191
  };
2257
2192
 
2258
- // src/exceptions/internal-server-error.exception.ts
2193
+ // src/exceptions/not-found.exception.ts
2259
2194
  var import_common25 = require("@nestjs/common");
2260
- var InternalServerErrorException3 = class extends BaseFieldException {
2195
+ var NotFoundException = class extends BaseFieldException {
2261
2196
  static {
2262
- __name(this, "InternalServerErrorException");
2197
+ __name(this, "NotFoundException");
2263
2198
  }
2264
2199
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2265
2200
  if (Array.isArray(messageOrField)) {
2266
- super(messageOrField, import_common25.HttpStatus.INTERNAL_SERVER_ERROR, fieldMessageOrDetail);
2201
+ super(messageOrField, import_common25.HttpStatus.NOT_FOUND, fieldMessageOrDetail);
2267
2202
  } else if (detail !== void 0) {
2268
- super(messageOrField, fieldMessageOrDetail, import_common25.HttpStatus.INTERNAL_SERVER_ERROR, detail);
2203
+ super(messageOrField, fieldMessageOrDetail, import_common25.HttpStatus.NOT_FOUND, detail);
2269
2204
  } else if (fieldMessageOrDetail) {
2270
- super(messageOrField, fieldMessageOrDetail, import_common25.HttpStatus.INTERNAL_SERVER_ERROR);
2205
+ super(messageOrField, fieldMessageOrDetail, import_common25.HttpStatus.NOT_FOUND);
2271
2206
  } else {
2272
- super(messageOrField, import_common25.HttpStatus.INTERNAL_SERVER_ERROR);
2207
+ super(messageOrField, import_common25.HttpStatus.NOT_FOUND);
2273
2208
  }
2274
2209
  }
2275
2210
  };
2276
2211
 
2277
- // src/exceptions/validation.exception.ts
2212
+ // src/exceptions/not-implemented.exception.ts
2278
2213
  var import_common26 = require("@nestjs/common");
2279
- var ValidationException = class extends BaseFieldException {
2214
+ var NotImplementedException = class extends BaseFieldException {
2280
2215
  static {
2281
- __name(this, "ValidationException");
2216
+ __name(this, "NotImplementedException");
2282
2217
  }
2283
- constructor(errors, detail) {
2284
- super(errors, import_common26.HttpStatus.BAD_REQUEST, detail);
2218
+ constructor(messageOrField, fieldMessageOrDetail, detail) {
2219
+ if (Array.isArray(messageOrField)) {
2220
+ super(messageOrField, import_common26.HttpStatus.NOT_IMPLEMENTED, fieldMessageOrDetail);
2221
+ } else if (detail !== void 0) {
2222
+ super(messageOrField, fieldMessageOrDetail, import_common26.HttpStatus.NOT_IMPLEMENTED, detail);
2223
+ } else if (fieldMessageOrDetail) {
2224
+ super(messageOrField, fieldMessageOrDetail, import_common26.HttpStatus.NOT_IMPLEMENTED);
2225
+ } else {
2226
+ super(messageOrField, import_common26.HttpStatus.NOT_IMPLEMENTED);
2227
+ }
2285
2228
  }
2286
2229
  };
2287
2230
 
2288
- // src/exceptions/unprocessable-entity.exception.ts
2231
+ // src/exceptions/payload-too-large.exception.ts
2289
2232
  var import_common27 = require("@nestjs/common");
2290
- var UnprocessableEntityException = class extends BaseFieldException {
2233
+ var PayloadTooLargeException = class extends BaseFieldException {
2291
2234
  static {
2292
- __name(this, "UnprocessableEntityException");
2235
+ __name(this, "PayloadTooLargeException");
2293
2236
  }
2294
2237
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2295
2238
  if (Array.isArray(messageOrField)) {
2296
- super(messageOrField, import_common27.HttpStatus.UNPROCESSABLE_ENTITY, fieldMessageOrDetail);
2239
+ super(messageOrField, import_common27.HttpStatus.PAYLOAD_TOO_LARGE, fieldMessageOrDetail);
2297
2240
  } else if (detail !== void 0) {
2298
- super(messageOrField, fieldMessageOrDetail, import_common27.HttpStatus.UNPROCESSABLE_ENTITY, detail);
2241
+ super(messageOrField, fieldMessageOrDetail, import_common27.HttpStatus.PAYLOAD_TOO_LARGE, detail);
2299
2242
  } else if (fieldMessageOrDetail) {
2300
- super(messageOrField, fieldMessageOrDetail, import_common27.HttpStatus.UNPROCESSABLE_ENTITY);
2243
+ super(messageOrField, fieldMessageOrDetail, import_common27.HttpStatus.PAYLOAD_TOO_LARGE);
2301
2244
  } else {
2302
- super(messageOrField, import_common27.HttpStatus.UNPROCESSABLE_ENTITY);
2245
+ super(messageOrField, import_common27.HttpStatus.PAYLOAD_TOO_LARGE);
2303
2246
  }
2304
2247
  }
2305
2248
  };
2306
2249
 
2307
- // src/exceptions/too-many-requests.exception.ts
2250
+ // src/exceptions/request-timeout.exception.ts
2308
2251
  var import_common28 = require("@nestjs/common");
2309
- var TooManyRequestsException = class extends BaseFieldException {
2252
+ var RequestTimeoutException = class extends BaseFieldException {
2310
2253
  static {
2311
- __name(this, "TooManyRequestsException");
2254
+ __name(this, "RequestTimeoutException");
2312
2255
  }
2313
2256
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2314
2257
  if (Array.isArray(messageOrField)) {
2315
- super(messageOrField, import_common28.HttpStatus.TOO_MANY_REQUESTS, fieldMessageOrDetail);
2258
+ super(messageOrField, import_common28.HttpStatus.REQUEST_TIMEOUT, fieldMessageOrDetail);
2316
2259
  } else if (detail !== void 0) {
2317
- super(messageOrField, fieldMessageOrDetail, import_common28.HttpStatus.TOO_MANY_REQUESTS, detail);
2260
+ super(messageOrField, fieldMessageOrDetail, import_common28.HttpStatus.REQUEST_TIMEOUT, detail);
2318
2261
  } else if (fieldMessageOrDetail) {
2319
- super(messageOrField, fieldMessageOrDetail, import_common28.HttpStatus.TOO_MANY_REQUESTS);
2262
+ super(messageOrField, fieldMessageOrDetail, import_common28.HttpStatus.REQUEST_TIMEOUT);
2320
2263
  } else {
2321
- super(messageOrField, import_common28.HttpStatus.TOO_MANY_REQUESTS);
2264
+ super(messageOrField, import_common28.HttpStatus.REQUEST_TIMEOUT);
2322
2265
  }
2323
2266
  }
2324
2267
  };
@@ -2342,217 +2285,521 @@ var ServiceUnavailableException = class extends BaseFieldException {
2342
2285
  }
2343
2286
  };
2344
2287
 
2345
- // src/exceptions/method-not-allowed.exception.ts
2288
+ // src/exceptions/too-many-requests.exception.ts
2346
2289
  var import_common30 = require("@nestjs/common");
2347
- var MethodNotAllowedException = class extends BaseFieldException {
2290
+ var TooManyRequestsException = class extends BaseFieldException {
2348
2291
  static {
2349
- __name(this, "MethodNotAllowedException");
2292
+ __name(this, "TooManyRequestsException");
2350
2293
  }
2351
2294
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2352
2295
  if (Array.isArray(messageOrField)) {
2353
- super(messageOrField, import_common30.HttpStatus.METHOD_NOT_ALLOWED, fieldMessageOrDetail);
2296
+ super(messageOrField, import_common30.HttpStatus.TOO_MANY_REQUESTS, fieldMessageOrDetail);
2354
2297
  } else if (detail !== void 0) {
2355
- super(messageOrField, fieldMessageOrDetail, import_common30.HttpStatus.METHOD_NOT_ALLOWED, detail);
2298
+ super(messageOrField, fieldMessageOrDetail, import_common30.HttpStatus.TOO_MANY_REQUESTS, detail);
2356
2299
  } else if (fieldMessageOrDetail) {
2357
- super(messageOrField, fieldMessageOrDetail, import_common30.HttpStatus.METHOD_NOT_ALLOWED);
2300
+ super(messageOrField, fieldMessageOrDetail, import_common30.HttpStatus.TOO_MANY_REQUESTS);
2358
2301
  } else {
2359
- super(messageOrField, import_common30.HttpStatus.METHOD_NOT_ALLOWED);
2302
+ super(messageOrField, import_common30.HttpStatus.TOO_MANY_REQUESTS);
2360
2303
  }
2361
2304
  }
2362
2305
  };
2363
2306
 
2364
- // src/exceptions/gone.exception.ts
2307
+ // src/exceptions/unauthorized.exception.ts
2365
2308
  var import_common31 = require("@nestjs/common");
2366
- var GoneException = class extends BaseFieldException {
2309
+ var UnauthorizedException4 = class extends BaseFieldException {
2367
2310
  static {
2368
- __name(this, "GoneException");
2311
+ __name(this, "UnauthorizedException");
2369
2312
  }
2370
2313
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2371
2314
  if (Array.isArray(messageOrField)) {
2372
- super(messageOrField, import_common31.HttpStatus.GONE, fieldMessageOrDetail);
2315
+ super(messageOrField, import_common31.HttpStatus.UNAUTHORIZED, fieldMessageOrDetail);
2373
2316
  } else if (detail !== void 0) {
2374
- super(messageOrField, fieldMessageOrDetail, import_common31.HttpStatus.GONE, detail);
2317
+ super(messageOrField, fieldMessageOrDetail, import_common31.HttpStatus.UNAUTHORIZED, detail);
2375
2318
  } else if (fieldMessageOrDetail) {
2376
- super(messageOrField, fieldMessageOrDetail, import_common31.HttpStatus.GONE);
2319
+ super(messageOrField, fieldMessageOrDetail, import_common31.HttpStatus.UNAUTHORIZED);
2377
2320
  } else {
2378
- super(messageOrField, import_common31.HttpStatus.GONE);
2321
+ super(messageOrField, import_common31.HttpStatus.UNAUTHORIZED);
2379
2322
  }
2380
2323
  }
2381
2324
  };
2382
2325
 
2383
- // src/exceptions/not-acceptable.exception.ts
2326
+ // src/exceptions/unprocessable-entity.exception.ts
2384
2327
  var import_common32 = require("@nestjs/common");
2385
- var NotAcceptableException = class extends BaseFieldException {
2328
+ var UnprocessableEntityException = class extends BaseFieldException {
2386
2329
  static {
2387
- __name(this, "NotAcceptableException");
2330
+ __name(this, "UnprocessableEntityException");
2388
2331
  }
2389
2332
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2390
2333
  if (Array.isArray(messageOrField)) {
2391
- super(messageOrField, import_common32.HttpStatus.NOT_ACCEPTABLE, fieldMessageOrDetail);
2334
+ super(messageOrField, import_common32.HttpStatus.UNPROCESSABLE_ENTITY, fieldMessageOrDetail);
2392
2335
  } else if (detail !== void 0) {
2393
- super(messageOrField, fieldMessageOrDetail, import_common32.HttpStatus.NOT_ACCEPTABLE, detail);
2336
+ super(messageOrField, fieldMessageOrDetail, import_common32.HttpStatus.UNPROCESSABLE_ENTITY, detail);
2394
2337
  } else if (fieldMessageOrDetail) {
2395
- super(messageOrField, fieldMessageOrDetail, import_common32.HttpStatus.NOT_ACCEPTABLE);
2338
+ super(messageOrField, fieldMessageOrDetail, import_common32.HttpStatus.UNPROCESSABLE_ENTITY);
2396
2339
  } else {
2397
- super(messageOrField, import_common32.HttpStatus.NOT_ACCEPTABLE);
2340
+ super(messageOrField, import_common32.HttpStatus.UNPROCESSABLE_ENTITY);
2398
2341
  }
2399
2342
  }
2400
2343
  };
2401
2344
 
2402
- // src/exceptions/request-timeout.exception.ts
2345
+ // src/exceptions/unsupported-media-type.exception.ts
2403
2346
  var import_common33 = require("@nestjs/common");
2404
- var RequestTimeoutException = class extends BaseFieldException {
2347
+ var UnsupportedMediaTypeException = class extends BaseFieldException {
2405
2348
  static {
2406
- __name(this, "RequestTimeoutException");
2349
+ __name(this, "UnsupportedMediaTypeException");
2407
2350
  }
2408
2351
  constructor(messageOrField, fieldMessageOrDetail, detail) {
2409
2352
  if (Array.isArray(messageOrField)) {
2410
- super(messageOrField, import_common33.HttpStatus.REQUEST_TIMEOUT, fieldMessageOrDetail);
2353
+ super(messageOrField, import_common33.HttpStatus.UNSUPPORTED_MEDIA_TYPE, fieldMessageOrDetail);
2411
2354
  } else if (detail !== void 0) {
2412
- super(messageOrField, fieldMessageOrDetail, import_common33.HttpStatus.REQUEST_TIMEOUT, detail);
2355
+ super(messageOrField, fieldMessageOrDetail, import_common33.HttpStatus.UNSUPPORTED_MEDIA_TYPE, detail);
2413
2356
  } else if (fieldMessageOrDetail) {
2414
- super(messageOrField, fieldMessageOrDetail, import_common33.HttpStatus.REQUEST_TIMEOUT);
2357
+ super(messageOrField, fieldMessageOrDetail, import_common33.HttpStatus.UNSUPPORTED_MEDIA_TYPE);
2415
2358
  } else {
2416
- super(messageOrField, import_common33.HttpStatus.REQUEST_TIMEOUT);
2359
+ super(messageOrField, import_common33.HttpStatus.UNSUPPORTED_MEDIA_TYPE);
2417
2360
  }
2418
2361
  }
2419
2362
  };
2420
2363
 
2421
- // src/exceptions/payload-too-large.exception.ts
2364
+ // src/exceptions/validation.exception.ts
2422
2365
  var import_common34 = require("@nestjs/common");
2423
- var PayloadTooLargeException = class extends BaseFieldException {
2366
+ var ValidationException = class extends BaseFieldException {
2424
2367
  static {
2425
- __name(this, "PayloadTooLargeException");
2368
+ __name(this, "ValidationException");
2426
2369
  }
2427
- constructor(messageOrField, fieldMessageOrDetail, detail) {
2428
- if (Array.isArray(messageOrField)) {
2429
- super(messageOrField, import_common34.HttpStatus.PAYLOAD_TOO_LARGE, fieldMessageOrDetail);
2430
- } else if (detail !== void 0) {
2431
- super(messageOrField, fieldMessageOrDetail, import_common34.HttpStatus.PAYLOAD_TOO_LARGE, detail);
2432
- } else if (fieldMessageOrDetail) {
2433
- super(messageOrField, fieldMessageOrDetail, import_common34.HttpStatus.PAYLOAD_TOO_LARGE);
2434
- } else {
2435
- super(messageOrField, import_common34.HttpStatus.PAYLOAD_TOO_LARGE);
2436
- }
2370
+ constructor(errors, detail) {
2371
+ super(errors, import_common34.HttpStatus.BAD_REQUEST, detail);
2437
2372
  }
2438
2373
  };
2439
2374
 
2440
- // src/exceptions/unsupported-media-type.exception.ts
2375
+ // src/filters/http-exception.filter.ts
2441
2376
  var import_common35 = require("@nestjs/common");
2442
- var UnsupportedMediaTypeException = class extends BaseFieldException {
2377
+ function _ts_decorate11(decorators, target, key, desc) {
2378
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2379
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2380
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2381
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2382
+ }
2383
+ __name(_ts_decorate11, "_ts_decorate");
2384
+ function getHttpStatusTitle(status) {
2385
+ const enumKey = Object.entries(import_common35.HttpStatus).find(([key, value]) => value === status && Number.isNaN(Number(key)))?.[0];
2386
+ if (!enumKey) {
2387
+ return "Error";
2388
+ }
2389
+ return enumKey.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
2390
+ }
2391
+ __name(getHttpStatusTitle, "getHttpStatusTitle");
2392
+ var HttpExceptionFilter = class _HttpExceptionFilter {
2443
2393
  static {
2444
- __name(this, "UnsupportedMediaTypeException");
2394
+ __name(this, "HttpExceptionFilter");
2445
2395
  }
2446
- constructor(messageOrField, fieldMessageOrDetail, detail) {
2447
- if (Array.isArray(messageOrField)) {
2448
- super(messageOrField, import_common35.HttpStatus.UNSUPPORTED_MEDIA_TYPE, fieldMessageOrDetail);
2449
- } else if (detail !== void 0) {
2450
- super(messageOrField, fieldMessageOrDetail, import_common35.HttpStatus.UNSUPPORTED_MEDIA_TYPE, detail);
2451
- } else if (fieldMessageOrDetail) {
2452
- super(messageOrField, fieldMessageOrDetail, import_common35.HttpStatus.UNSUPPORTED_MEDIA_TYPE);
2396
+ logger = new import_common35.Logger(_HttpExceptionFilter.name);
2397
+ catch(exception, host) {
2398
+ const ctx = host.switchToHttp();
2399
+ const response = ctx.getResponse();
2400
+ let status = import_common35.HttpStatus.INTERNAL_SERVER_ERROR;
2401
+ let errors = [];
2402
+ let detail = "Internal server error";
2403
+ if (exception instanceof import_common35.HttpException) {
2404
+ status = exception.getStatus();
2405
+ const exceptionResponse = exception.getResponse();
2406
+ if (typeof exceptionResponse === "object" && exceptionResponse !== null) {
2407
+ const responseObj = exceptionResponse;
2408
+ if ("errors" in responseObj && Array.isArray(responseObj.errors)) {
2409
+ errors = responseObj.errors;
2410
+ detail = ("detail" in responseObj ? responseObj.detail : void 0) || exception.message;
2411
+ } else if ("message" in responseObj && Array.isArray(responseObj.message)) {
2412
+ errors = responseObj.message.map((msg) => {
2413
+ if (typeof msg === "object" && "property" in msg && "constraints" in msg) {
2414
+ const constraintValues = Object.values(msg.constraints);
2415
+ return {
2416
+ field: msg.property,
2417
+ message: constraintValues[0] ?? "Validation failed"
2418
+ };
2419
+ }
2420
+ return {
2421
+ message: typeof msg === "string" ? msg : JSON.stringify(msg)
2422
+ };
2423
+ });
2424
+ detail = "Validation failed";
2425
+ } else if ("message" in responseObj) {
2426
+ const message = responseObj.message;
2427
+ errors = [
2428
+ {
2429
+ message: Array.isArray(message) ? message.join(", ") : message
2430
+ }
2431
+ ];
2432
+ detail = ("error" in responseObj ? responseObj.error : void 0) || exception.message;
2433
+ }
2434
+ } else if (typeof exceptionResponse === "string") {
2435
+ errors = [
2436
+ {
2437
+ message: exceptionResponse
2438
+ }
2439
+ ];
2440
+ detail = exceptionResponse;
2441
+ }
2453
2442
  } else {
2454
- super(messageOrField, import_common35.HttpStatus.UNSUPPORTED_MEDIA_TYPE);
2443
+ const errorMessage = exception instanceof Error ? exception.message : "Unknown error";
2444
+ const stack = exception instanceof Error ? exception.stack : void 0;
2445
+ this.logger.error(`Unexpected error: ${errorMessage}`, stack);
2446
+ errors = [
2447
+ {
2448
+ message: "An unexpected error occurred"
2449
+ }
2450
+ ];
2455
2451
  }
2452
+ const problemDetails = {
2453
+ title: getHttpStatusTitle(status),
2454
+ status,
2455
+ detail,
2456
+ errors
2457
+ };
2458
+ response.status(status).send(problemDetails);
2456
2459
  }
2457
2460
  };
2461
+ HttpExceptionFilter = _ts_decorate11([
2462
+ (0, import_common35.Catch)()
2463
+ ], HttpExceptionFilter);
2458
2464
 
2459
- // src/exceptions/not-implemented.exception.ts
2465
+ // src/http/guards/csrf.guard.ts
2460
2466
  var import_common36 = require("@nestjs/common");
2461
- var NotImplementedException = class extends BaseFieldException {
2467
+ function _ts_decorate12(decorators, target, key, desc) {
2468
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2469
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2470
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2471
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2472
+ }
2473
+ __name(_ts_decorate12, "_ts_decorate");
2474
+ var CsrfGuard = class _CsrfGuard {
2462
2475
  static {
2463
- __name(this, "NotImplementedException");
2476
+ __name(this, "CsrfGuard");
2464
2477
  }
2465
- constructor(messageOrField, fieldMessageOrDetail, detail) {
2466
- if (Array.isArray(messageOrField)) {
2467
- super(messageOrField, import_common36.HttpStatus.NOT_IMPLEMENTED, fieldMessageOrDetail);
2468
- } else if (detail !== void 0) {
2469
- super(messageOrField, fieldMessageOrDetail, import_common36.HttpStatus.NOT_IMPLEMENTED, detail);
2470
- } else if (fieldMessageOrDetail) {
2471
- super(messageOrField, fieldMessageOrDetail, import_common36.HttpStatus.NOT_IMPLEMENTED);
2472
- } else {
2473
- super(messageOrField, import_common36.HttpStatus.NOT_IMPLEMENTED);
2478
+ logger = new import_common36.Logger(_CsrfGuard.name);
2479
+ async canActivate(context) {
2480
+ const request = context.switchToHttp().getRequest();
2481
+ const reply = context.switchToHttp().getResponse();
2482
+ const safeMethods = [
2483
+ "GET",
2484
+ "HEAD",
2485
+ "OPTIONS"
2486
+ ];
2487
+ if (safeMethods.includes(request.method)) {
2488
+ return true;
2489
+ }
2490
+ try {
2491
+ const fastifyInstance = request.server;
2492
+ if (!fastifyInstance.csrfProtection) {
2493
+ this.logger.error("CSRF protection plugin not found. Ensure @fastify/csrf-protection is registered.");
2494
+ throw new import_common36.ForbiddenException("CSRF protection not configured");
2495
+ }
2496
+ await new Promise((resolve, reject) => {
2497
+ fastifyInstance.csrfProtection(request, reply, (err) => {
2498
+ if (err) {
2499
+ reject(err);
2500
+ } else {
2501
+ resolve();
2502
+ }
2503
+ });
2504
+ });
2505
+ this.logger.debug(`CSRF validation successful for ${request.method} ${request.url}`);
2506
+ return true;
2507
+ } catch (error) {
2508
+ this.logger.warn(`CSRF validation failed for ${request.method} ${request.url}: ${error instanceof Error ? error.message : "Unknown error"}`);
2509
+ throw new import_common36.ForbiddenException({
2510
+ errors: [
2511
+ {
2512
+ field: "csrf",
2513
+ message: "Invalid or missing CSRF token"
2514
+ }
2515
+ ],
2516
+ message: "CSRF validation failed"
2517
+ });
2474
2518
  }
2475
2519
  }
2476
2520
  };
2521
+ CsrfGuard = _ts_decorate12([
2522
+ (0, import_common36.Injectable)()
2523
+ ], CsrfGuard);
2477
2524
 
2478
- // src/exceptions/bad-gateway.exception.ts
2525
+ // src/http/http.module.ts
2479
2526
  var import_common37 = require("@nestjs/common");
2480
- var BadGatewayException = class extends BaseFieldException {
2527
+ function _ts_decorate13(decorators, target, key, desc) {
2528
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2529
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2530
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2531
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2532
+ }
2533
+ __name(_ts_decorate13, "_ts_decorate");
2534
+ var HttpModule = class {
2481
2535
  static {
2482
- __name(this, "BadGatewayException");
2536
+ __name(this, "HttpModule");
2483
2537
  }
2484
- constructor(messageOrField, fieldMessageOrDetail, detail) {
2485
- if (Array.isArray(messageOrField)) {
2486
- super(messageOrField, import_common37.HttpStatus.BAD_GATEWAY, fieldMessageOrDetail);
2487
- } else if (detail !== void 0) {
2488
- super(messageOrField, fieldMessageOrDetail, import_common37.HttpStatus.BAD_GATEWAY, detail);
2489
- } else if (fieldMessageOrDetail) {
2490
- super(messageOrField, fieldMessageOrDetail, import_common37.HttpStatus.BAD_GATEWAY);
2491
- } else {
2492
- super(messageOrField, import_common37.HttpStatus.BAD_GATEWAY);
2538
+ };
2539
+ HttpModule = _ts_decorate13([
2540
+ (0, import_common37.Module)({
2541
+ providers: [
2542
+ CsrfGuard
2543
+ ],
2544
+ exports: [
2545
+ CsrfGuard
2546
+ ]
2547
+ })
2548
+ ], HttpModule);
2549
+
2550
+ // src/logger/interceptors/http-logger.interceptor.ts
2551
+ var import_common38 = require("@nestjs/common");
2552
+ var import_operators2 = require("rxjs/operators");
2553
+
2554
+ // src/logger/utils/index.ts
2555
+ var import_node_async_hooks = require("async_hooks");
2556
+ var import_node_crypto = require("crypto");
2557
+ var correlationStorage = new import_node_async_hooks.AsyncLocalStorage();
2558
+ function getCorrelationContext() {
2559
+ return correlationStorage.getStore();
2560
+ }
2561
+ __name(getCorrelationContext, "getCorrelationContext");
2562
+ function runWithCorrelationContext(context, callback) {
2563
+ return correlationStorage.run(context, callback);
2564
+ }
2565
+ __name(runWithCorrelationContext, "runWithCorrelationContext");
2566
+ function updateCorrelationContext(updates) {
2567
+ const context = correlationStorage.getStore();
2568
+ if (context) {
2569
+ Object.assign(context, updates);
2570
+ }
2571
+ }
2572
+ __name(updateCorrelationContext, "updateCorrelationContext");
2573
+ var DEFAULT_CORRELATION_HEADER = "x-correlation-id";
2574
+ function generateCorrelationId() {
2575
+ return (0, import_node_crypto.randomUUID)();
2576
+ }
2577
+ __name(generateCorrelationId, "generateCorrelationId");
2578
+ function addCorrelationIdToResponse(reply, correlationId, headerName = DEFAULT_CORRELATION_HEADER) {
2579
+ if (typeof reply.header === "function") {
2580
+ reply.header(headerName, correlationId);
2581
+ } else if (reply.raw && typeof reply.raw.setHeader === "function") {
2582
+ reply.raw.setHeader(headerName, correlationId);
2583
+ }
2584
+ }
2585
+ __name(addCorrelationIdToResponse, "addCorrelationIdToResponse");
2586
+
2587
+ // src/logger/interceptors/http-logger.interceptor.ts
2588
+ function _ts_decorate14(decorators, target, key, desc) {
2589
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2590
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2591
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2592
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2593
+ }
2594
+ __name(_ts_decorate14, "_ts_decorate");
2595
+ function _ts_metadata7(k, v) {
2596
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2597
+ }
2598
+ __name(_ts_metadata7, "_ts_metadata");
2599
+ function _ts_param4(paramIndex, decorator) {
2600
+ return function(target, key) {
2601
+ decorator(target, key, paramIndex);
2602
+ };
2603
+ }
2604
+ __name(_ts_param4, "_ts_param");
2605
+ var HttpLoggerInterceptor = class {
2606
+ static {
2607
+ __name(this, "HttpLoggerInterceptor");
2608
+ }
2609
+ logger;
2610
+ enableRequestLog;
2611
+ enableResponseLog;
2612
+ slowRequestThreshold;
2613
+ constructor(logger, options) {
2614
+ this.logger = logger;
2615
+ this.enableRequestLog = options?.enableRequestLog ?? true;
2616
+ this.enableResponseLog = options?.enableResponseLog ?? true;
2617
+ this.slowRequestThreshold = options?.slowRequestThreshold ?? 3e3;
2618
+ }
2619
+ intercept(context, next) {
2620
+ if (context.getType() !== "http") {
2621
+ return next.handle();
2622
+ }
2623
+ const httpContext = context.switchToHttp();
2624
+ const request = httpContext.getRequest();
2625
+ const response = httpContext.getResponse();
2626
+ const startTime = Date.now();
2627
+ if (this.enableRequestLog) {
2628
+ this.logRequest(request);
2629
+ }
2630
+ return next.handle().pipe((0, import_operators2.tap)(() => {
2631
+ if (this.enableResponseLog) {
2632
+ const duration = Date.now() - startTime;
2633
+ this.logResponse(request, response, duration);
2634
+ }
2635
+ }), (0, import_operators2.catchError)((error) => {
2636
+ const duration = Date.now() - startTime;
2637
+ this.logError(request, response, duration, error);
2638
+ throw error;
2639
+ }));
2640
+ }
2641
+ logRequest(request) {
2642
+ try {
2643
+ const correlationContext = getCorrelationContext();
2644
+ const metadata = {
2645
+ type: "http_request",
2646
+ method: request.method,
2647
+ url: request.url,
2648
+ correlationId: correlationContext?.correlationId,
2649
+ ip: request.ip,
2650
+ userAgent: request.headers["user-agent"]
2651
+ };
2652
+ this.logger.logWithMetadata("log", `Incoming ${request.method} ${request.url}`, metadata);
2653
+ } catch (error) {
2654
+ this.logger.error("Failed to log HTTP request", error.stack);
2655
+ }
2656
+ }
2657
+ logResponse(request, response, duration) {
2658
+ try {
2659
+ const correlationContext = getCorrelationContext();
2660
+ const statusCode = response.statusCode;
2661
+ const logLevel = statusCode >= 500 ? "error" : statusCode >= 400 ? "warn" : "log";
2662
+ const metadata = {
2663
+ type: "http_response",
2664
+ method: request.method,
2665
+ url: request.url,
2666
+ statusCode,
2667
+ duration,
2668
+ correlationId: correlationContext?.correlationId
2669
+ };
2670
+ if (duration > this.slowRequestThreshold) {
2671
+ metadata.slowRequest = true;
2672
+ }
2673
+ const message = metadata.slowRequest ? `SLOW ${request.method} ${request.url} ${statusCode} - ${duration}ms` : `${request.method} ${request.url} ${statusCode} - ${duration}ms`;
2674
+ this.logger.logWithMetadata(logLevel, message, metadata);
2675
+ } catch (error) {
2676
+ this.logger.error("Failed to log HTTP response", error.stack);
2677
+ }
2678
+ }
2679
+ logError(request, response, duration, error) {
2680
+ try {
2681
+ const correlationContext = getCorrelationContext();
2682
+ const statusCode = response.statusCode || 500;
2683
+ const metadata = {
2684
+ type: "http_error",
2685
+ method: request.method,
2686
+ url: request.url,
2687
+ statusCode,
2688
+ duration,
2689
+ correlationId: correlationContext?.correlationId,
2690
+ errorName: error?.name || "Error",
2691
+ errorMessage: error?.message || "Unknown error"
2692
+ };
2693
+ if (error?.stack) {
2694
+ metadata.trace = error.stack;
2695
+ }
2696
+ if (error?.response) {
2697
+ metadata.errorDetails = error.response;
2698
+ }
2699
+ const message = `ERROR ${request.method} ${request.url} ${statusCode} - ${error?.message || "Unknown error"}`;
2700
+ this.logger.logWithMetadata("error", message, metadata);
2701
+ } catch (loggingError) {
2702
+ this.logger.error("Failed to log HTTP error", loggingError.stack);
2703
+ }
2704
+ }
2705
+ };
2706
+ HttpLoggerInterceptor = _ts_decorate14([
2707
+ (0, import_common38.Injectable)(),
2708
+ _ts_param4(1, (0, import_common38.Optional)()),
2709
+ _ts_metadata7("design:type", Function),
2710
+ _ts_metadata7("design:paramtypes", [
2711
+ typeof LoggerService === "undefined" ? Object : LoggerService,
2712
+ typeof HttpLoggerOptions === "undefined" ? Object : HttpLoggerOptions
2713
+ ])
2714
+ ], HttpLoggerInterceptor);
2715
+
2716
+ // src/logger/logger.module.ts
2717
+ var import_common41 = require("@nestjs/common");
2718
+
2719
+ // src/logger/middleware/correlation-id.middleware.ts
2720
+ var import_common39 = require("@nestjs/common");
2721
+ function _ts_decorate15(decorators, target, key, desc) {
2722
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2723
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2724
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2725
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2726
+ }
2727
+ __name(_ts_decorate15, "_ts_decorate");
2728
+ function _ts_metadata8(k, v) {
2729
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2730
+ }
2731
+ __name(_ts_metadata8, "_ts_metadata");
2732
+ var CorrelationIdMiddleware = class {
2733
+ static {
2734
+ __name(this, "CorrelationIdMiddleware");
2735
+ }
2736
+ includeInResponse;
2737
+ responseHeader;
2738
+ constructor(options = {}) {
2739
+ this.includeInResponse = options.includeInResponse ?? true;
2740
+ this.responseHeader = options.responseHeader ?? DEFAULT_CORRELATION_HEADER;
2741
+ }
2742
+ /**
2743
+ * Middleware handler for processing requests.
2744
+ */
2745
+ use(_req, reply, next) {
2746
+ const correlationId = generateCorrelationId();
2747
+ if (this.includeInResponse) {
2748
+ addCorrelationIdToResponse(reply, correlationId, this.responseHeader);
2749
+ }
2750
+ runWithCorrelationContext({
2751
+ correlationId
2752
+ }, () => {
2753
+ next();
2754
+ });
2755
+ }
2756
+ /**
2757
+ * Fastify hook handler for onRequest.
2758
+ * This is an async function that returns a Promise, ensuring the AsyncLocalStorage
2759
+ * context persists throughout the entire request lifecycle.
2760
+ */
2761
+ async onRequest(_req, reply) {
2762
+ const correlationId = generateCorrelationId();
2763
+ if (this.includeInResponse) {
2764
+ addCorrelationIdToResponse(reply, correlationId, this.responseHeader);
2765
+ }
2766
+ const store = correlationStorage.getStore();
2767
+ if (!store) {
2768
+ correlationStorage.enterWith({
2769
+ correlationId
2770
+ });
2493
2771
  }
2494
2772
  }
2495
2773
  };
2496
-
2497
- // src/logger/logger.module.ts
2498
- var import_common41 = require("@nestjs/common");
2774
+ CorrelationIdMiddleware = _ts_decorate15([
2775
+ (0, import_common39.Injectable)(),
2776
+ _ts_metadata8("design:type", Function),
2777
+ _ts_metadata8("design:paramtypes", [
2778
+ typeof CorrelationIdMiddlewareOptions === "undefined" ? Object : CorrelationIdMiddlewareOptions
2779
+ ])
2780
+ ], CorrelationIdMiddleware);
2499
2781
 
2500
2782
  // src/logger/services/logger.service.ts
2501
- var import_common38 = require("@nestjs/common");
2783
+ var import_common40 = require("@nestjs/common");
2502
2784
  var import_winston = require("winston");
2503
2785
  var import_winston_daily_rotate_file = __toESM(require("winston-daily-rotate-file"), 1);
2504
-
2505
- // src/logger/utils/index.ts
2506
- var import_node_async_hooks = require("async_hooks");
2507
- var import_node_crypto = require("crypto");
2508
- var correlationStorage = new import_node_async_hooks.AsyncLocalStorage();
2509
- function getCorrelationContext() {
2510
- return correlationStorage.getStore();
2511
- }
2512
- __name(getCorrelationContext, "getCorrelationContext");
2513
- function runWithCorrelationContext(context, callback) {
2514
- return correlationStorage.run(context, callback);
2515
- }
2516
- __name(runWithCorrelationContext, "runWithCorrelationContext");
2517
- function updateCorrelationContext(updates) {
2518
- const context = correlationStorage.getStore();
2519
- if (context) {
2520
- Object.assign(context, updates);
2521
- }
2522
- }
2523
- __name(updateCorrelationContext, "updateCorrelationContext");
2524
- var DEFAULT_CORRELATION_HEADER = "x-correlation-id";
2525
- function generateCorrelationId() {
2526
- return (0, import_node_crypto.randomUUID)();
2527
- }
2528
- __name(generateCorrelationId, "generateCorrelationId");
2529
- function addCorrelationIdToResponse(reply, correlationId, headerName = DEFAULT_CORRELATION_HEADER) {
2530
- if (typeof reply.header === "function") {
2531
- reply.header(headerName, correlationId);
2532
- } else if (reply.raw && typeof reply.raw.setHeader === "function") {
2533
- reply.raw.setHeader(headerName, correlationId);
2534
- }
2535
- }
2536
- __name(addCorrelationIdToResponse, "addCorrelationIdToResponse");
2537
-
2538
- // src/logger/services/logger.service.ts
2539
- function _ts_decorate14(decorators, target, key, desc) {
2786
+ function _ts_decorate16(decorators, target, key, desc) {
2540
2787
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2541
2788
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2542
2789
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2543
2790
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2544
2791
  }
2545
- __name(_ts_decorate14, "_ts_decorate");
2546
- function _ts_metadata8(k, v) {
2792
+ __name(_ts_decorate16, "_ts_decorate");
2793
+ function _ts_metadata9(k, v) {
2547
2794
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2548
2795
  }
2549
- __name(_ts_metadata8, "_ts_metadata");
2550
- function _ts_param4(paramIndex, decorator) {
2796
+ __name(_ts_metadata9, "_ts_metadata");
2797
+ function _ts_param5(paramIndex, decorator) {
2551
2798
  return function(target, key) {
2552
2799
  decorator(target, key, paramIndex);
2553
2800
  };
2554
2801
  }
2555
- __name(_ts_param4, "_ts_param");
2802
+ __name(_ts_param5, "_ts_param");
2556
2803
  var LoggerService2 = class _LoggerService {
2557
2804
  static {
2558
2805
  __name(this, "LoggerService");
@@ -2605,7 +2852,8 @@ var LoggerService2 = class _LoggerService {
2605
2852
  ].filter(Boolean);
2606
2853
  let output = parts.join(" ");
2607
2854
  if (trace) {
2608
- output += "\n" + trace;
2855
+ output += `
2856
+ ${trace}`;
2609
2857
  }
2610
2858
  return output;
2611
2859
  }), import_winston.format.colorize({
@@ -2753,210 +3001,16 @@ var LoggerService2 = class _LoggerService {
2753
3001
  return childLogger;
2754
3002
  }
2755
3003
  };
2756
- LoggerService2 = _ts_decorate14([
2757
- (0, import_common38.Injectable)(),
2758
- _ts_param4(0, (0, import_common38.Optional)()),
2759
- _ts_param4(1, (0, import_common38.Optional)()),
2760
- _ts_metadata8("design:type", Function),
2761
- _ts_metadata8("design:paramtypes", [
2762
- typeof LoggerModuleOptions === "undefined" ? Object : LoggerModuleOptions,
2763
- typeof import_common38.Logger === "undefined" ? Object : import_common38.Logger
2764
- ])
2765
- ], LoggerService2);
2766
-
2767
- // src/logger/middleware/correlation-id.middleware.ts
2768
- var import_common39 = require("@nestjs/common");
2769
- function _ts_decorate15(decorators, target, key, desc) {
2770
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2771
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2772
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2773
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2774
- }
2775
- __name(_ts_decorate15, "_ts_decorate");
2776
- function _ts_metadata9(k, v) {
2777
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2778
- }
2779
- __name(_ts_metadata9, "_ts_metadata");
2780
- var CorrelationIdMiddleware = class {
2781
- static {
2782
- __name(this, "CorrelationIdMiddleware");
2783
- }
2784
- includeInResponse;
2785
- responseHeader;
2786
- constructor(options = {}) {
2787
- this.includeInResponse = options.includeInResponse ?? true;
2788
- this.responseHeader = options.responseHeader ?? DEFAULT_CORRELATION_HEADER;
2789
- }
2790
- /**
2791
- * Middleware handler for processing requests.
2792
- */
2793
- use(req, reply, next) {
2794
- const correlationId = generateCorrelationId();
2795
- if (this.includeInResponse) {
2796
- addCorrelationIdToResponse(reply, correlationId, this.responseHeader);
2797
- }
2798
- runWithCorrelationContext({
2799
- correlationId
2800
- }, () => {
2801
- next();
2802
- });
2803
- }
2804
- /**
2805
- * Fastify hook handler for onRequest.
2806
- * This is an async function that returns a Promise, ensuring the AsyncLocalStorage
2807
- * context persists throughout the entire request lifecycle.
2808
- */
2809
- async onRequest(req, reply) {
2810
- const correlationId = generateCorrelationId();
2811
- if (this.includeInResponse) {
2812
- addCorrelationIdToResponse(reply, correlationId, this.responseHeader);
2813
- }
2814
- const store = correlationStorage.getStore();
2815
- if (!store) {
2816
- correlationStorage.enterWith({
2817
- correlationId
2818
- });
2819
- }
2820
- }
2821
- };
2822
- CorrelationIdMiddleware = _ts_decorate15([
2823
- (0, import_common39.Injectable)(),
2824
- _ts_metadata9("design:type", Function),
2825
- _ts_metadata9("design:paramtypes", [
2826
- typeof CorrelationIdMiddlewareOptions === "undefined" ? Object : CorrelationIdMiddlewareOptions
2827
- ])
2828
- ], CorrelationIdMiddleware);
2829
-
2830
- // src/logger/interceptors/http-logger.interceptor.ts
2831
- var import_common40 = require("@nestjs/common");
2832
- var import_operators2 = require("rxjs/operators");
2833
- function _ts_decorate16(decorators, target, key, desc) {
2834
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2835
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2836
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2837
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2838
- }
2839
- __name(_ts_decorate16, "_ts_decorate");
2840
- function _ts_metadata10(k, v) {
2841
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2842
- }
2843
- __name(_ts_metadata10, "_ts_metadata");
2844
- function _ts_param5(paramIndex, decorator) {
2845
- return function(target, key) {
2846
- decorator(target, key, paramIndex);
2847
- };
2848
- }
2849
- __name(_ts_param5, "_ts_param");
2850
- var HttpLoggerInterceptor = class {
2851
- static {
2852
- __name(this, "HttpLoggerInterceptor");
2853
- }
2854
- logger;
2855
- enableRequestLog;
2856
- enableResponseLog;
2857
- slowRequestThreshold;
2858
- constructor(logger, options) {
2859
- this.logger = logger;
2860
- this.enableRequestLog = options?.enableRequestLog ?? true;
2861
- this.enableResponseLog = options?.enableResponseLog ?? true;
2862
- this.slowRequestThreshold = options?.slowRequestThreshold ?? 3e3;
2863
- }
2864
- intercept(context, next) {
2865
- if (context.getType() !== "http") {
2866
- return next.handle();
2867
- }
2868
- const httpContext = context.switchToHttp();
2869
- const request = httpContext.getRequest();
2870
- const response = httpContext.getResponse();
2871
- const startTime = Date.now();
2872
- if (this.enableRequestLog) {
2873
- this.logRequest(request);
2874
- }
2875
- return next.handle().pipe((0, import_operators2.tap)(() => {
2876
- if (this.enableResponseLog) {
2877
- const duration = Date.now() - startTime;
2878
- this.logResponse(request, response, duration);
2879
- }
2880
- }), (0, import_operators2.catchError)((error) => {
2881
- const duration = Date.now() - startTime;
2882
- this.logError(request, response, duration, error);
2883
- throw error;
2884
- }));
2885
- }
2886
- logRequest(request) {
2887
- try {
2888
- const correlationContext = getCorrelationContext();
2889
- const metadata = {
2890
- type: "http_request",
2891
- method: request.method,
2892
- url: request.url,
2893
- correlationId: correlationContext?.correlationId,
2894
- ip: request.ip,
2895
- userAgent: request.headers["user-agent"]
2896
- };
2897
- this.logger.logWithMetadata("log", `Incoming ${request.method} ${request.url}`, metadata);
2898
- } catch (error) {
2899
- this.logger.error("Failed to log HTTP request", error.stack);
2900
- }
2901
- }
2902
- logResponse(request, response, duration) {
2903
- try {
2904
- const correlationContext = getCorrelationContext();
2905
- const statusCode = response.statusCode;
2906
- const logLevel = statusCode >= 500 ? "error" : statusCode >= 400 ? "warn" : "log";
2907
- const metadata = {
2908
- type: "http_response",
2909
- method: request.method,
2910
- url: request.url,
2911
- statusCode,
2912
- duration,
2913
- correlationId: correlationContext?.correlationId
2914
- };
2915
- if (duration > this.slowRequestThreshold) {
2916
- metadata.slowRequest = true;
2917
- }
2918
- const message = metadata.slowRequest ? `SLOW ${request.method} ${request.url} ${statusCode} - ${duration}ms` : `${request.method} ${request.url} ${statusCode} - ${duration}ms`;
2919
- this.logger.logWithMetadata(logLevel, message, metadata);
2920
- } catch (error) {
2921
- this.logger.error("Failed to log HTTP response", error.stack);
2922
- }
2923
- }
2924
- logError(request, response, duration, error) {
2925
- try {
2926
- const correlationContext = getCorrelationContext();
2927
- const statusCode = response.statusCode || 500;
2928
- const metadata = {
2929
- type: "http_error",
2930
- method: request.method,
2931
- url: request.url,
2932
- statusCode,
2933
- duration,
2934
- correlationId: correlationContext?.correlationId,
2935
- errorName: error?.name || "Error",
2936
- errorMessage: error?.message || "Unknown error"
2937
- };
2938
- if (error?.stack) {
2939
- metadata.trace = error.stack;
2940
- }
2941
- if (error?.response) {
2942
- metadata.errorDetails = error.response;
2943
- }
2944
- const message = `ERROR ${request.method} ${request.url} ${statusCode} - ${error?.message || "Unknown error"}`;
2945
- this.logger.logWithMetadata("error", message, metadata);
2946
- } catch (loggingError) {
2947
- this.logger.error("Failed to log HTTP error", loggingError.stack);
2948
- }
2949
- }
2950
- };
2951
- HttpLoggerInterceptor = _ts_decorate16([
3004
+ LoggerService2 = _ts_decorate16([
2952
3005
  (0, import_common40.Injectable)(),
3006
+ _ts_param5(0, (0, import_common40.Optional)()),
2953
3007
  _ts_param5(1, (0, import_common40.Optional)()),
2954
- _ts_metadata10("design:type", Function),
2955
- _ts_metadata10("design:paramtypes", [
2956
- typeof LoggerService === "undefined" ? Object : LoggerService,
2957
- typeof HttpLoggerOptions === "undefined" ? Object : HttpLoggerOptions
3008
+ _ts_metadata9("design:type", Function),
3009
+ _ts_metadata9("design:paramtypes", [
3010
+ typeof LoggerModuleOptions === "undefined" ? Object : LoggerModuleOptions,
3011
+ typeof Logger === "undefined" ? Object : Logger
2958
3012
  ])
2959
- ], HttpLoggerInterceptor);
3013
+ ], LoggerService2);
2960
3014
 
2961
3015
  // src/logger/logger.module.ts
2962
3016
  function _ts_decorate17(decorators, target, key, desc) {
@@ -3229,7 +3283,7 @@ var LoggerModule = class _LoggerModule {
3229
3283
  * ```
3230
3284
  */
3231
3285
  static forRootAsync(options) {
3232
- const asyncProviders = this.createAsyncProviders(options);
3286
+ const asyncProviders = _LoggerModule.createAsyncProviders(options);
3233
3287
  return {
3234
3288
  module: _LoggerModule,
3235
3289
  imports: options.imports || [],
@@ -3305,7 +3359,7 @@ var LoggerModule = class _LoggerModule {
3305
3359
  * Configures middleware for the module.
3306
3360
  * Middleware is registered globally in main.ts using Fastify hooks.
3307
3361
  */
3308
- configure(consumer) {
3362
+ configure(_consumer) {
3309
3363
  }
3310
3364
  /**
3311
3365
  * Creates async providers for dynamic module configuration.
@@ -3313,11 +3367,11 @@ var LoggerModule = class _LoggerModule {
3313
3367
  static createAsyncProviders(options) {
3314
3368
  if (options.useFactory) {
3315
3369
  return [
3316
- this.createAsyncOptionsProvider(options)
3370
+ _LoggerModule.createAsyncOptionsProvider(options)
3317
3371
  ];
3318
3372
  }
3319
3373
  const providers = [
3320
- this.createAsyncOptionsProvider(options)
3374
+ _LoggerModule.createAsyncOptionsProvider(options)
3321
3375
  ];
3322
3376
  if (options.useClass) {
3323
3377
  providers.push({
@@ -3335,7 +3389,7 @@ var LoggerModule = class _LoggerModule {
3335
3389
  return {
3336
3390
  provide: LOGGER_MODULE_OPTIONS,
3337
3391
  useFactory: /* @__PURE__ */ __name(async (...args) => {
3338
- const userOptions = await options.useFactory(...args);
3392
+ const userOptions = await options.useFactory?.(...args);
3339
3393
  return mergeWithDefaults(userOptions);
3340
3394
  }, "useFactory"),
3341
3395
  inject: options.inject || []
@@ -3414,11 +3468,19 @@ LoggerModule = _ts_decorate17([
3414
3468
  ValidationException,
3415
3469
  VrittiAuthGuard,
3416
3470
  addCorrelationIdToResponse,
3471
+ configureApiSdk,
3417
3472
  correlationStorage,
3473
+ defineConfig,
3418
3474
  generateCorrelationId,
3475
+ getConfig,
3419
3476
  getCorrelationContext,
3420
3477
  getHttpStatusTitle,
3478
+ getJwtExpiry,
3479
+ getRefreshCookieOptions,
3480
+ hashToken,
3481
+ resetConfig,
3421
3482
  runWithCorrelationContext,
3422
- updateCorrelationContext
3483
+ updateCorrelationContext,
3484
+ verifyTokenHash
3423
3485
  });
3424
3486
  //# sourceMappingURL=index.cjs.map