@vritti/api-sdk 0.1.3 → 0.1.4

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
@@ -48,7 +48,7 @@ __export(index_exports, {
48
48
  InternalServerErrorException: () => InternalServerErrorException3,
49
49
  LOGGER_MODULE_OPTIONS: () => LOGGER_MODULE_OPTIONS,
50
50
  LoggerModule: () => LoggerModule,
51
- LoggerService: () => LoggerService2,
51
+ LoggerService: () => LoggerService,
52
52
  MethodNotAllowedException: () => MethodNotAllowedException,
53
53
  NotAcceptableException: () => NotAcceptableException,
54
54
  NotFoundException: () => NotFoundException,
@@ -56,13 +56,13 @@ __export(index_exports, {
56
56
  Onboarding: () => Onboarding,
57
57
  PayloadTooLargeException: () => PayloadTooLargeException,
58
58
  PrimaryBaseRepository: () => PrimaryBaseRepository,
59
- PrimaryDatabaseService: () => PrimaryDatabaseService2,
59
+ PrimaryDatabaseService: () => PrimaryDatabaseService,
60
60
  Public: () => Public,
61
61
  RequestTimeoutException: () => RequestTimeoutException,
62
62
  ServiceUnavailableException: () => ServiceUnavailableException,
63
63
  Tenant: () => Tenant,
64
64
  TenantBaseRepository: () => TenantBaseRepository,
65
- TenantContextService: () => TenantContextService2,
65
+ TenantContextService: () => TenantContextService,
66
66
  TenantDatabaseService: () => TenantDatabaseService,
67
67
  TooManyRequestsException: () => TooManyRequestsException,
68
68
  UnauthorizedException: () => UnauthorizedException4,
@@ -89,10 +89,10 @@ __export(index_exports, {
89
89
  module.exports = __toCommonJS(index_exports);
90
90
 
91
91
  // src/auth/auth-config.module.ts
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");
92
+ var import_common5 = require("@nestjs/common");
93
+ var import_config4 = require("@nestjs/config");
94
+ var import_core3 = require("@nestjs/core");
95
+ var import_jwt2 = require("@nestjs/jwt");
96
96
 
97
97
  // src/request/request.module.ts
98
98
  var import_common2 = require("@nestjs/common");
@@ -193,7 +193,7 @@ function _ts_param(paramIndex, decorator) {
193
193
  };
194
194
  }
195
195
  __name(_ts_param, "_ts_param");
196
- var RequestService2 = class {
196
+ var RequestService = class {
197
197
  static {
198
198
  __name(this, "RequestService");
199
199
  }
@@ -262,7 +262,7 @@ var RequestService2 = class {
262
262
  return this.request.headers || {};
263
263
  }
264
264
  };
265
- RequestService2 = _ts_decorate([
265
+ RequestService = _ts_decorate([
266
266
  (0, import_common.Injectable)({
267
267
  scope: import_common.Scope.REQUEST
268
268
  }),
@@ -271,7 +271,7 @@ RequestService2 = _ts_decorate([
271
271
  _ts_metadata("design:paramtypes", [
272
272
  typeof FastifyRequest === "undefined" ? Object : FastifyRequest
273
273
  ])
274
- ], RequestService2);
274
+ ], RequestService);
275
275
 
276
276
  // src/request/request.module.ts
277
277
  function _ts_decorate2(decorators, target, key, desc) {
@@ -290,16 +290,256 @@ RequestModule = _ts_decorate2([
290
290
  (0, import_common2.Global)(),
291
291
  (0, import_common2.Module)({
292
292
  providers: [
293
- RequestService2
293
+ RequestService
294
294
  ],
295
295
  exports: [
296
- RequestService2
296
+ RequestService
297
297
  ]
298
298
  })
299
299
  ], RequestModule);
300
300
 
301
301
  // src/auth/guards/vritti-auth.guard.ts
302
+ var import_common4 = require("@nestjs/common");
303
+ var import_config2 = require("@nestjs/config");
304
+ var import_core2 = require("@nestjs/core");
305
+ var import_jwt = require("@nestjs/jwt");
306
+
307
+ // src/database/services/primary-database.service.ts
302
308
  var import_common3 = require("@nestjs/common");
309
+ var import_drizzle_orm = require("drizzle-orm");
310
+ var import_node_postgres = require("drizzle-orm/node-postgres");
311
+ var import_pg = require("pg");
312
+
313
+ // src/database/constants.ts
314
+ var DATABASE_MODULE_OPTIONS = Symbol("DATABASE_MODULE_OPTIONS");
315
+
316
+ // src/database/services/primary-database.service.ts
317
+ function _ts_decorate3(decorators, target, key, desc) {
318
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
319
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
320
+ 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;
321
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
322
+ }
323
+ __name(_ts_decorate3, "_ts_decorate");
324
+ function _ts_metadata2(k, v) {
325
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
326
+ }
327
+ __name(_ts_metadata2, "_ts_metadata");
328
+ function _ts_param2(paramIndex, decorator) {
329
+ return function(target, key) {
330
+ decorator(target, key, paramIndex);
331
+ };
332
+ }
333
+ __name(_ts_param2, "_ts_param");
334
+ var PrimaryDatabaseService = class _PrimaryDatabaseService {
335
+ static {
336
+ __name(this, "PrimaryDatabaseService");
337
+ }
338
+ options;
339
+ logger = new import_common3.Logger(_PrimaryDatabaseService.name);
340
+ /** PostgreSQL connection pool */
341
+ pool = null;
342
+ /** Drizzle database instance */
343
+ db = null;
344
+ /** In-memory cache: Map<tenantIdentifier, TenantConfig> */
345
+ tenantConfigCache = /* @__PURE__ */ new Map();
346
+ /** Cache TTL in milliseconds */
347
+ cacheTTL;
348
+ constructor(options) {
349
+ this.options = options;
350
+ this.cacheTTL = options.connectionCacheTTL || 3e5;
351
+ }
352
+ async onModuleInit() {
353
+ if (this.options.primaryDb) {
354
+ await this.initializeDrizzleClient();
355
+ }
356
+ }
357
+ /**
358
+ * Initialize connection to primary database using Drizzle
359
+ */
360
+ async initializeDrizzleClient() {
361
+ try {
362
+ const databaseUrl = this.buildPrimaryDbUrl();
363
+ this.pool = new import_pg.Pool({
364
+ connectionString: databaseUrl,
365
+ max: this.options.maxConnections || 10
366
+ });
367
+ this.logger.debug(`Schema keys passed to drizzle: [${Object.keys(this.options.drizzleSchema || {}).join(", ")}]`);
368
+ this.logger.debug(`Relations keys passed to drizzle: [${Object.keys(this.options.drizzleRelations || {}).join(", ")}]`);
369
+ this.db = (0, import_node_postgres.drizzle)({
370
+ client: this.pool,
371
+ schema: this.options.drizzleSchema,
372
+ relations: this.options.drizzleRelations
373
+ });
374
+ this.logger.debug(`Drizzle query keys after init: [${Object.keys(this.db.query || {}).join(", ")}]`);
375
+ await this.pool.query("SELECT 1");
376
+ this.logger.log("Connected to primary database (tenant registry)");
377
+ } catch (error) {
378
+ this.logger.error("Failed to connect to primary database", error);
379
+ throw new import_common3.InternalServerErrorException("Failed to initialize tenant registry");
380
+ }
381
+ }
382
+ /**
383
+ * Build connection URL from primary database properties
384
+ */
385
+ buildPrimaryDbUrl() {
386
+ if (!this.options.primaryDb) {
387
+ throw new Error("Primary database configuration not provided");
388
+ }
389
+ const { host, port = 5432, username, password, database, schema = "public", sslMode = "require" } = this.options.primaryDb;
390
+ let url = `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
391
+ const params = new URLSearchParams();
392
+ if (schema) {
393
+ params.set("schema", schema);
394
+ }
395
+ params.set("sslmode", sslMode);
396
+ const queryString = params.toString();
397
+ if (queryString) {
398
+ url += `?${queryString}`;
399
+ }
400
+ this.logger.debug(`Primary DB connection URL: ${this.maskPassword(url)}`);
401
+ return url;
402
+ }
403
+ /**
404
+ * Mask password in connection URL for logging
405
+ */
406
+ maskPassword(url) {
407
+ return url.replace(/:([^@]+)@/, ":****@");
408
+ }
409
+ /**
410
+ * Get tenant configuration by identifier (ID or subdomain)
411
+ *
412
+ * @param tenantIdentifier Tenant ID or subdomain
413
+ * @returns Tenant configuration or null if not found
414
+ */
415
+ async getTenantInfo(tenantIdentifier) {
416
+ const cached = this.tenantConfigCache.get(tenantIdentifier);
417
+ if (cached) {
418
+ this.logger.debug(`Cache hit for tenant: ${tenantIdentifier}`);
419
+ return cached;
420
+ }
421
+ try {
422
+ if (!this.db) {
423
+ throw new Error("Primary database client not initialized");
424
+ }
425
+ this.logger.debug(`Querying primary database for tenant: ${tenantIdentifier}`);
426
+ const schema = this.options.drizzleSchema;
427
+ const { tenants, tenantDatabaseConfigs } = schema;
428
+ 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);
429
+ if (!result.length) {
430
+ this.logger.warn(`Tenant not found: ${tenantIdentifier}`);
431
+ return null;
432
+ }
433
+ const row = result[0];
434
+ const tenant = row.tenants;
435
+ const config = row.tenant_database_configs;
436
+ if (tenant.status !== "ACTIVE") {
437
+ this.logger.warn(`Tenant not active: ${tenantIdentifier}`);
438
+ return null;
439
+ }
440
+ const info = {
441
+ id: tenant.id,
442
+ subdomain: tenant.subdomain,
443
+ type: tenant.dbType,
444
+ status: tenant.status,
445
+ // For SHARED tenants: schema name
446
+ schemaName: config?.dbSchema || void 0,
447
+ // For DEDICATED tenants: database configuration from TenantDatabaseConfig table
448
+ databaseName: config?.dbName || void 0,
449
+ databaseHost: config?.dbHost || void 0,
450
+ databasePort: config?.dbPort || void 0,
451
+ databaseUsername: config?.dbUsername ? this.decrypt(config.dbUsername) : void 0,
452
+ databasePassword: config?.dbPassword ? this.decrypt(config.dbPassword) : void 0,
453
+ databaseSslMode: config?.dbSslMode || void 0,
454
+ connectionPoolSize: config?.connectionPoolSize || void 0
455
+ };
456
+ this.cacheInfo(info);
457
+ return info;
458
+ } catch (error) {
459
+ this.logger.error(`Failed to fetch tenant info: ${tenantIdentifier}`, error);
460
+ throw new import_common3.InternalServerErrorException("Failed to resolve tenant");
461
+ }
462
+ }
463
+ /**
464
+ * Cache tenant information with TTL
465
+ */
466
+ cacheInfo(info) {
467
+ this.tenantConfigCache.set(info.id, info);
468
+ this.tenantConfigCache.set(info.subdomain, info);
469
+ setTimeout(() => {
470
+ this.tenantConfigCache.delete(info.id);
471
+ this.tenantConfigCache.delete(info.subdomain);
472
+ this.logger.debug(`Cache expired for tenant: ${info.subdomain}`);
473
+ }, this.cacheTTL);
474
+ }
475
+ /**
476
+ * Clear cached tenant information
477
+ *
478
+ * Useful when tenant settings are updated and cache needs to be invalidated
479
+ *
480
+ * @param tenantIdentifier Tenant ID or subdomain
481
+ */
482
+ clearTenantCache(tenantIdentifier) {
483
+ const config = this.tenantConfigCache.get(tenantIdentifier);
484
+ if (config) {
485
+ this.tenantConfigCache.delete(config.id);
486
+ this.tenantConfigCache.delete(config.subdomain);
487
+ this.logger.log(`Cleared cache for tenant: ${tenantIdentifier}`);
488
+ }
489
+ }
490
+ /**
491
+ * Clear all cached tenant configurations
492
+ */
493
+ clearAllCaches() {
494
+ const size = this.tenantConfigCache.size;
495
+ this.tenantConfigCache.clear();
496
+ this.logger.log(`Cleared ${size} cached tenant configs`);
497
+ }
498
+ /**
499
+ * Get the Drizzle database instance for the primary database.
500
+ * This is a synchronous property that returns the initialized Drizzle client.
501
+ *
502
+ * @returns Primary database Drizzle instance
503
+ * @throws Error if primary database client is not initialized
504
+ */
505
+ get drizzleClient() {
506
+ if (!this.db) {
507
+ throw new Error("Primary database client not initialized");
508
+ }
509
+ return this.db;
510
+ }
511
+ /**
512
+ * Get the Drizzle schema
513
+ */
514
+ get schema() {
515
+ return this.options.drizzleSchema;
516
+ }
517
+ /**
518
+ * Decrypt database credentials
519
+ *
520
+ * Override this method to implement your encryption strategy
521
+ *
522
+ * @param encrypted Encrypted value
523
+ * @returns Decrypted value
524
+ */
525
+ decrypt(encrypted) {
526
+ return encrypted;
527
+ }
528
+ async onModuleDestroy() {
529
+ if (this.pool) {
530
+ await this.pool.end();
531
+ this.logger.log("Disconnected from primary database");
532
+ }
533
+ }
534
+ };
535
+ PrimaryDatabaseService = _ts_decorate3([
536
+ (0, import_common3.Injectable)(),
537
+ _ts_param2(0, (0, import_common3.Inject)(DATABASE_MODULE_OPTIONS)),
538
+ _ts_metadata2("design:type", Function),
539
+ _ts_metadata2("design:paramtypes", [
540
+ typeof DatabaseModuleOptions === "undefined" ? Object : DatabaseModuleOptions
541
+ ])
542
+ ], PrimaryDatabaseService);
303
543
 
304
544
  // src/auth/utils/token-hash.util.ts
305
545
  var crypto = __toESM(require("crypto"), 1);
@@ -315,17 +555,17 @@ function verifyTokenHash(token, expectedHash) {
315
555
  __name(verifyTokenHash, "verifyTokenHash");
316
556
 
317
557
  // src/auth/guards/vritti-auth.guard.ts
318
- function _ts_decorate3(decorators, target, key, desc) {
558
+ function _ts_decorate4(decorators, target, key, desc) {
319
559
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
320
560
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
321
561
  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;
322
562
  return c > 3 && r && Object.defineProperty(target, key, r), r;
323
563
  }
324
- __name(_ts_decorate3, "_ts_decorate");
325
- function _ts_metadata2(k, v) {
564
+ __name(_ts_decorate4, "_ts_decorate");
565
+ function _ts_metadata3(k, v) {
326
566
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
327
567
  }
328
- __name(_ts_metadata2, "_ts_metadata");
568
+ __name(_ts_metadata3, "_ts_metadata");
329
569
  var VrittiAuthGuard = class _VrittiAuthGuard {
330
570
  static {
331
571
  __name(this, "VrittiAuthGuard");
@@ -335,7 +575,7 @@ var VrittiAuthGuard = class _VrittiAuthGuard {
335
575
  jwtService;
336
576
  primaryDatabase;
337
577
  requestService;
338
- logger = new import_common3.Logger(_VrittiAuthGuard.name);
578
+ logger = new import_common4.Logger(_VrittiAuthGuard.name);
339
579
  constructor(reflector, _configService, jwtService, primaryDatabase, requestService) {
340
580
  this.reflector = reflector;
341
581
  this._configService = _configService;
@@ -361,17 +601,17 @@ var VrittiAuthGuard = class _VrittiAuthGuard {
361
601
  const accessToken = this.requestService.getAccessToken();
362
602
  if (!accessToken) {
363
603
  this.logger.warn("Access token not found in Authorization header");
364
- throw new import_common3.UnauthorizedException("Access token not found");
604
+ throw new import_common4.UnauthorizedException("Access token not found");
365
605
  }
366
606
  const decodedToken = this.jwtService.decode(accessToken);
367
607
  if (!decodedToken) {
368
608
  this.logger.warn("Failed to decode access token");
369
- throw new import_common3.UnauthorizedException("Invalid token format");
609
+ throw new import_common4.UnauthorizedException("Invalid token format");
370
610
  }
371
611
  if (isOnboarding) {
372
612
  if (decodedToken.type !== "onboarding") {
373
613
  this.logger.warn("Onboarding endpoint requires onboarding token");
374
- throw new import_common3.UnauthorizedException("This endpoint requires an onboarding token");
614
+ throw new import_common4.UnauthorizedException("This endpoint requires an onboarding token");
375
615
  }
376
616
  const validatedToken2 = this.validateAccessToken(accessToken);
377
617
  this.logger.debug("Onboarding token validated successfully");
@@ -384,7 +624,7 @@ var VrittiAuthGuard = class _VrittiAuthGuard {
384
624
  }
385
625
  if (decodedToken.type === "onboarding") {
386
626
  this.logger.warn("Regular endpoint accessed with onboarding token");
387
- throw new import_common3.UnauthorizedException("Onboarding tokens cannot access this endpoint");
627
+ throw new import_common4.UnauthorizedException("Onboarding tokens cannot access this endpoint");
388
628
  }
389
629
  const validatedToken = this.validateAccessToken(accessToken);
390
630
  this.logger.debug("Access token validated successfully");
@@ -396,7 +636,7 @@ var VrittiAuthGuard = class _VrittiAuthGuard {
396
636
  const tenantIdentifier = this.requestService.getTenantIdentifier();
397
637
  if (!tenantIdentifier) {
398
638
  this.logger.warn("Tenant identifier not found in request");
399
- throw new import_common3.UnauthorizedException("Tenant identifier not found");
639
+ throw new import_common4.UnauthorizedException("Tenant identifier not found");
400
640
  }
401
641
  this.logger.debug(`Tenant identifier extracted: ${tenantIdentifier}`);
402
642
  if (tenantIdentifier === "cloud") {
@@ -406,20 +646,20 @@ var VrittiAuthGuard = class _VrittiAuthGuard {
406
646
  const tenantInfo = await this.primaryDatabase.getTenantInfo(tenantIdentifier);
407
647
  if (!tenantInfo) {
408
648
  this.logger.warn(`Invalid tenant: ${tenantIdentifier}`);
409
- throw new import_common3.UnauthorizedException("Invalid tenant");
649
+ throw new import_common4.UnauthorizedException("Invalid tenant");
410
650
  }
411
651
  if (tenantInfo.status !== "ACTIVE") {
412
652
  this.logger.warn(`Tenant ${tenantIdentifier} has status: ${tenantInfo.status}`);
413
- throw new import_common3.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
653
+ throw new import_common4.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
414
654
  }
415
655
  this.logger.debug(`Tenant validated: ${tenantInfo.subdomain} (${tenantInfo.type})`);
416
656
  return true;
417
657
  } catch (error) {
418
- if (error instanceof import_common3.UnauthorizedException) {
658
+ if (error instanceof import_common4.UnauthorizedException) {
419
659
  throw error;
420
660
  }
421
661
  this.logger.error("Unexpected error in auth guard", error);
422
- throw new import_common3.UnauthorizedException("Authentication failed");
662
+ throw new import_common4.UnauthorizedException("Authentication failed");
423
663
  }
424
664
  }
425
665
  /**
@@ -438,24 +678,24 @@ var VrittiAuthGuard = class _VrittiAuthGuard {
438
678
  }
439
679
  return decoded;
440
680
  } catch (error) {
441
- if (error instanceof import_common3.UnauthorizedException) {
681
+ if (error instanceof import_common4.UnauthorizedException) {
442
682
  throw error;
443
683
  }
444
684
  const jwtError = error;
445
685
  if (jwtError?.name === "TokenExpiredError") {
446
686
  this.logger.warn(`Access token expired at: ${jwtError?.expiredAt}`);
447
- throw new import_common3.UnauthorizedException("Access token has expired");
687
+ throw new import_common4.UnauthorizedException("Access token has expired");
448
688
  }
449
689
  if (jwtError?.name === "JsonWebTokenError") {
450
690
  this.logger.warn(`Access token verification failed: ${jwtError?.message}`);
451
- throw new import_common3.UnauthorizedException("Invalid access token");
691
+ throw new import_common4.UnauthorizedException("Invalid access token");
452
692
  }
453
693
  if (jwtError?.name === "NotBeforeError") {
454
694
  this.logger.warn("Access token used before valid (nbf claim)");
455
- throw new import_common3.UnauthorizedException("Access token not yet valid");
695
+ throw new import_common4.UnauthorizedException("Access token not yet valid");
456
696
  }
457
697
  this.logger.error("Unexpected error validating access token", error);
458
- throw new import_common3.UnauthorizedException("Access token validation failed");
698
+ throw new import_common4.UnauthorizedException("Access token validation failed");
459
699
  }
460
700
  }
461
701
  /**
@@ -482,37 +722,37 @@ var VrittiAuthGuard = class _VrittiAuthGuard {
482
722
  const refreshToken = cookies[config.cookie.refreshCookieName];
483
723
  if (!refreshToken) {
484
724
  this.logger.warn("Session validation failed - refresh token cookie not found");
485
- throw new import_common3.UnauthorizedException("Session validation failed");
725
+ throw new import_common4.UnauthorizedException("Session validation failed");
486
726
  }
487
727
  if (!verifyTokenHash(refreshToken, validatedToken.refreshTokenHash)) {
488
728
  this.logger.warn("Session validation failed - token binding mismatch");
489
- throw new import_common3.UnauthorizedException("Session validation failed");
729
+ throw new import_common4.UnauthorizedException("Session validation failed");
490
730
  }
491
731
  this.logger.debug("Token binding validated successfully");
492
732
  }
493
733
  };
494
- VrittiAuthGuard = _ts_decorate3([
495
- (0, import_common3.Injectable)({
496
- scope: import_common3.Scope.REQUEST
734
+ VrittiAuthGuard = _ts_decorate4([
735
+ (0, import_common4.Injectable)({
736
+ scope: import_common4.Scope.REQUEST
497
737
  }),
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,
738
+ _ts_metadata3("design:type", Function),
739
+ _ts_metadata3("design:paramtypes", [
740
+ typeof import_core2.Reflector === "undefined" ? Object : import_core2.Reflector,
741
+ typeof import_config2.ConfigService === "undefined" ? Object : import_config2.ConfigService,
742
+ typeof import_jwt.JwtService === "undefined" ? Object : import_jwt.JwtService,
503
743
  typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
504
744
  typeof RequestService === "undefined" ? Object : RequestService
505
745
  ])
506
746
  ], VrittiAuthGuard);
507
747
 
508
748
  // src/auth/auth-config.module.ts
509
- function _ts_decorate4(decorators, target, key, desc) {
749
+ function _ts_decorate5(decorators, target, key, desc) {
510
750
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
511
751
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
512
752
  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
753
  return c > 3 && r && Object.defineProperty(target, key, r), r;
514
754
  }
515
- __name(_ts_decorate4, "_ts_decorate");
755
+ __name(_ts_decorate5, "_ts_decorate");
516
756
  var AuthConfigModule = class _AuthConfigModule {
517
757
  static {
518
758
  __name(this, "AuthConfigModule");
@@ -531,14 +771,14 @@ var AuthConfigModule = class _AuthConfigModule {
531
771
  return {
532
772
  module: _AuthConfigModule,
533
773
  imports: [
534
- import_config3.ConfigModule,
774
+ import_config4.ConfigModule,
535
775
  RequestModule,
536
- import_jwt.JwtModule.registerAsync({
776
+ import_jwt2.JwtModule.registerAsync({
537
777
  imports: [
538
- import_config3.ConfigModule
778
+ import_config4.ConfigModule
539
779
  ],
540
780
  inject: [
541
- import_config3.ConfigService
781
+ import_config4.ConfigService
542
782
  ],
543
783
  useFactory: /* @__PURE__ */ __name((config) => ({
544
784
  secret: config.get("JWT_SECRET"),
@@ -550,56 +790,141 @@ var AuthConfigModule = class _AuthConfigModule {
550
790
  ],
551
791
  providers: [
552
792
  {
553
- provide: import_core2.APP_GUARD,
793
+ provide: import_core3.APP_GUARD,
554
794
  useClass: VrittiAuthGuard
555
795
  }
556
796
  ],
557
797
  exports: [
558
- import_jwt.JwtModule
798
+ import_jwt2.JwtModule
559
799
  ]
560
800
  };
561
801
  }
562
802
  };
563
- AuthConfigModule = _ts_decorate4([
564
- (0, import_common4.Global)(),
565
- (0, import_common4.Module)({})
803
+ AuthConfigModule = _ts_decorate5([
804
+ (0, import_common5.Global)(),
805
+ (0, import_common5.Module)({})
566
806
  ], AuthConfigModule);
567
807
 
568
808
  // 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");
809
+ var import_common6 = require("@nestjs/common");
810
+ var Onboarding = /* @__PURE__ */ __name(() => (0, import_common6.SetMetadata)("isOnboarding", true), "Onboarding");
571
811
 
572
812
  // 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");
813
+ var import_common7 = require("@nestjs/common");
814
+ var Public = /* @__PURE__ */ __name(() => (0, import_common7.SetMetadata)("isPublic", true), "Public");
575
815
 
576
816
  // src/database/database.module.ts
577
817
  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");
818
+ var import_core5 = require("@nestjs/core");
582
819
 
583
820
  // src/database/interceptors/message-tenant-context.interceptor.ts
584
- var import_common7 = require("@nestjs/common");
821
+ var import_common9 = require("@nestjs/common");
585
822
  var import_operators = require("rxjs/operators");
586
- function _ts_decorate5(decorators, target, key, desc) {
823
+
824
+ // src/database/services/tenant-context.service.ts
825
+ var import_common8 = require("@nestjs/common");
826
+ function _ts_decorate6(decorators, target, key, desc) {
587
827
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
588
828
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
589
829
  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
830
  return c > 3 && r && Object.defineProperty(target, key, r), r;
591
831
  }
592
- __name(_ts_decorate5, "_ts_decorate");
593
- function _ts_metadata3(k, v) {
832
+ __name(_ts_decorate6, "_ts_decorate");
833
+ var TenantContextService = class {
834
+ static {
835
+ __name(this, "TenantContextService");
836
+ }
837
+ tenantInfo = null;
838
+ /**
839
+ * Set tenant information for this request/message
840
+ *
841
+ * This is typically called by:
842
+ * - TenantContextInterceptor (for HTTP requests in gateway)
843
+ * - MessageTenantContextInterceptor (for RabbitMQ messages in microservices)
844
+ * - Manual context setup in message handlers
845
+ *
846
+ * @param tenantInfo Complete tenant information
847
+ * @throws Error if tenant context is already set (prevents accidental overwrites)
848
+ */
849
+ setTenant(tenantInfo) {
850
+ if (this.tenantInfo) {
851
+ throw new Error("Tenant context already set for this request");
852
+ }
853
+ this.tenantInfo = tenantInfo;
854
+ }
855
+ /**
856
+ * Get tenant information for this request/message
857
+ *
858
+ * @returns Tenant information
859
+ * @throws UnauthorizedException if tenant context hasn't been set
860
+ */
861
+ getTenant() {
862
+ if (!this.tenantInfo) {
863
+ throw new import_common8.UnauthorizedException("Tenant context not set");
864
+ }
865
+ return this.tenantInfo;
866
+ }
867
+ /**
868
+ * Check if tenant context has been set
869
+ *
870
+ * @returns true if tenant context is available
871
+ */
872
+ hasTenant() {
873
+ return this.tenantInfo !== null;
874
+ }
875
+ /**
876
+ * Clear tenant context
877
+ *
878
+ * This is useful for cleanup in RabbitMQ message handlers
879
+ * after the message has been processed.
880
+ *
881
+ * HTTP requests don't need manual cleanup as the service
882
+ * instance is destroyed when the request ends.
883
+ */
884
+ clearTenant() {
885
+ this.tenantInfo = null;
886
+ }
887
+ /**
888
+ * Get tenant ID safely (returns null if not set)
889
+ *
890
+ * @returns Tenant ID or null
891
+ */
892
+ getTenantIdSafe() {
893
+ return this.tenantInfo?.id ?? null;
894
+ }
895
+ /**
896
+ * Get tenant subdomain safely (returns null if not set)
897
+ *
898
+ * @returns Tenant subdomain or null
899
+ */
900
+ getTenantSubdomainSafe() {
901
+ return this.tenantInfo?.subdomain ?? null;
902
+ }
903
+ };
904
+ TenantContextService = _ts_decorate6([
905
+ (0, import_common8.Injectable)({
906
+ scope: import_common8.Scope.REQUEST
907
+ })
908
+ ], TenantContextService);
909
+
910
+ // src/database/interceptors/message-tenant-context.interceptor.ts
911
+ function _ts_decorate7(decorators, target, key, desc) {
912
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
913
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
914
+ 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;
915
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
916
+ }
917
+ __name(_ts_decorate7, "_ts_decorate");
918
+ function _ts_metadata4(k, v) {
594
919
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
595
920
  }
596
- __name(_ts_metadata3, "_ts_metadata");
921
+ __name(_ts_metadata4, "_ts_metadata");
597
922
  var MessageTenantContextInterceptor = class _MessageTenantContextInterceptor {
598
923
  static {
599
924
  __name(this, "MessageTenantContextInterceptor");
600
925
  }
601
926
  tenantContext;
602
- logger = new import_common7.Logger(_MessageTenantContextInterceptor.name);
927
+ logger = new import_common9.Logger(_MessageTenantContextInterceptor.name);
603
928
  constructor(tenantContext) {
604
929
  this.tenantContext = tenantContext;
605
930
  }
@@ -644,29 +969,30 @@ var MessageTenantContextInterceptor = class _MessageTenantContextInterceptor {
644
969
  }
645
970
  }
646
971
  };
647
- MessageTenantContextInterceptor = _ts_decorate5([
648
- (0, import_common7.Injectable)({
649
- scope: import_common7.Scope.REQUEST
972
+ MessageTenantContextInterceptor = _ts_decorate7([
973
+ (0, import_common9.Injectable)({
974
+ scope: import_common9.Scope.REQUEST
650
975
  }),
651
- _ts_metadata3("design:type", Function),
652
- _ts_metadata3("design:paramtypes", [
976
+ _ts_metadata4("design:type", Function),
977
+ _ts_metadata4("design:paramtypes", [
653
978
  typeof TenantContextService === "undefined" ? Object : TenantContextService
654
979
  ])
655
980
  ], MessageTenantContextInterceptor);
656
981
 
657
982
  // src/database/interceptors/tenant-context.interceptor.ts
658
- var import_common8 = require("@nestjs/common");
659
- function _ts_decorate6(decorators, target, key, desc) {
983
+ var import_common10 = require("@nestjs/common");
984
+ var import_core4 = require("@nestjs/core");
985
+ function _ts_decorate8(decorators, target, key, desc) {
660
986
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
661
987
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
662
988
  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;
663
989
  return c > 3 && r && Object.defineProperty(target, key, r), r;
664
990
  }
665
- __name(_ts_decorate6, "_ts_decorate");
666
- function _ts_metadata4(k, v) {
991
+ __name(_ts_decorate8, "_ts_decorate");
992
+ function _ts_metadata5(k, v) {
667
993
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
668
994
  }
669
- __name(_ts_metadata4, "_ts_metadata");
995
+ __name(_ts_metadata5, "_ts_metadata");
670
996
  var TenantContextInterceptor = class _TenantContextInterceptor {
671
997
  static {
672
998
  __name(this, "TenantContextInterceptor");
@@ -675,7 +1001,7 @@ var TenantContextInterceptor = class _TenantContextInterceptor {
675
1001
  tenantContext;
676
1002
  primaryDatabase;
677
1003
  requestService;
678
- logger = new import_common8.Logger(_TenantContextInterceptor.name);
1004
+ logger = new import_common10.Logger(_TenantContextInterceptor.name);
679
1005
  constructor(reflector, tenantContext, primaryDatabase, requestService) {
680
1006
  this.reflector = reflector;
681
1007
  this.tenantContext = tenantContext;
@@ -696,7 +1022,7 @@ var TenantContextInterceptor = class _TenantContextInterceptor {
696
1022
  return next.handle();
697
1023
  }
698
1024
  if (!tenantIdentifier) {
699
- throw new import_common8.UnauthorizedException("Tenant identifier not found in request");
1025
+ throw new import_common10.UnauthorizedException("Tenant identifier not found in request");
700
1026
  }
701
1027
  this.logger.debug(`Tenant identifier extracted: ${tenantIdentifier}`);
702
1028
  if (tenantIdentifier === "cloud") {
@@ -706,353 +1032,35 @@ var TenantContextInterceptor = class _TenantContextInterceptor {
706
1032
  const tenantInfo = await this.primaryDatabase.getTenantInfo(tenantIdentifier);
707
1033
  if (!tenantInfo) {
708
1034
  this.logger.warn(`Invalid tenant: ${tenantIdentifier}`);
709
- throw new import_common8.UnauthorizedException("Invalid tenant");
1035
+ throw new import_common10.UnauthorizedException("Invalid tenant");
710
1036
  }
711
1037
  if (tenantInfo.status !== "ACTIVE") {
712
- this.logger.warn(`Tenant ${tenantIdentifier} has status: ${tenantInfo.status}`);
713
- throw new import_common8.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
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}`);
719
- } catch (error) {
720
- this.logger.error("Failed to set tenant context", error);
721
- throw error;
722
- }
723
- return next.handle();
724
- }
725
- };
726
- TenantContextInterceptor = _ts_decorate6([
727
- (0, import_common8.Injectable)({
728
- scope: import_common8.Scope.REQUEST
729
- }),
730
- _ts_metadata4("design:type", Function),
731
- _ts_metadata4("design:paramtypes", [
732
- typeof Reflector === "undefined" ? Object : Reflector,
733
- typeof TenantContextService === "undefined" ? Object : TenantContextService,
734
- typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
735
- typeof RequestService === "undefined" ? Object : RequestService
736
- ])
737
- ], TenantContextInterceptor);
738
-
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) {
745
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
746
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
748
- return c > 3 && r && Object.defineProperty(target, key, r), r;
749
- }
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 {
762
- static {
763
- __name(this, "PrimaryDatabaseService");
764
- }
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;
778
- }
779
- async onModuleInit() {
780
- if (this.options.primaryDb) {
781
- await this.initializeDrizzleClient();
782
- }
783
- }
784
- /**
785
- * Initialize connection to primary database using Drizzle
786
- */
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");
807
- }
808
- }
809
- /**
810
- * Build connection URL from primary database properties
811
- */
812
- buildPrimaryDbUrl() {
813
- if (!this.options.primaryDb) {
814
- throw new Error("Primary database configuration not provided");
815
- }
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;
829
- }
830
- /**
831
- * Mask password in connection URL for logging
832
- */
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;
1021
- }
1022
- /**
1023
- * Clear tenant context
1024
- *
1025
- * This is useful for cleanup in RabbitMQ message handlers
1026
- * after the message has been processed.
1027
- *
1028
- * HTTP requests don't need manual cleanup as the service
1029
- * instance is destroyed when the request ends.
1030
- */
1031
- clearTenant() {
1032
- this.tenantInfo = null;
1033
- }
1034
- /**
1035
- * Get tenant ID safely (returns null if not set)
1036
- *
1037
- * @returns Tenant ID or null
1038
- */
1039
- getTenantIdSafe() {
1040
- return this.tenantInfo?.id ?? null;
1041
- }
1042
- /**
1043
- * Get tenant subdomain safely (returns null if not set)
1044
- *
1045
- * @returns Tenant subdomain or null
1046
- */
1047
- getTenantSubdomainSafe() {
1048
- return this.tenantInfo?.subdomain ?? null;
1038
+ this.logger.warn(`Tenant ${tenantIdentifier} has status: ${tenantInfo.status}`);
1039
+ throw new import_common10.UnauthorizedException(`Tenant is ${tenantInfo.status}`);
1040
+ }
1041
+ this.logger.debug(`Tenant config loaded: ${tenantInfo.subdomain} (${tenantInfo.type})`);
1042
+ this.tenantContext.setTenant(tenantInfo);
1043
+ request.tenant = tenantInfo;
1044
+ this.logger.log(`Tenant context set: ${tenantInfo.subdomain}`);
1045
+ } catch (error) {
1046
+ this.logger.error("Failed to set tenant context", error);
1047
+ throw error;
1048
+ }
1049
+ return next.handle();
1049
1050
  }
1050
1051
  };
1051
- TenantContextService2 = _ts_decorate8([
1052
+ TenantContextInterceptor = _ts_decorate8([
1052
1053
  (0, import_common10.Injectable)({
1053
1054
  scope: import_common10.Scope.REQUEST
1054
- })
1055
- ], TenantContextService2);
1055
+ }),
1056
+ _ts_metadata5("design:type", Function),
1057
+ _ts_metadata5("design:paramtypes", [
1058
+ typeof import_core4.Reflector === "undefined" ? Object : import_core4.Reflector,
1059
+ typeof TenantContextService === "undefined" ? Object : TenantContextService,
1060
+ typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
1061
+ typeof RequestService === "undefined" ? Object : RequestService
1062
+ ])
1063
+ ], TenantContextInterceptor);
1056
1064
 
1057
1065
  // src/database/services/tenant-database.service.ts
1058
1066
  var import_common11 = require("@nestjs/common");
@@ -1339,18 +1347,18 @@ var DatabaseModule = class _DatabaseModule {
1339
1347
  };
1340
1348
  const providers = [
1341
1349
  asyncProvider,
1342
- TenantContextService2,
1343
- PrimaryDatabaseService2,
1350
+ TenantContextService,
1351
+ PrimaryDatabaseService,
1344
1352
  TenantDatabaseService
1345
1353
  ];
1346
1354
  if (mode === "server") {
1347
1355
  providers.push({
1348
- provide: import_core3.APP_INTERCEPTOR,
1356
+ provide: import_core5.APP_INTERCEPTOR,
1349
1357
  useClass: TenantContextInterceptor
1350
1358
  });
1351
1359
  } else {
1352
1360
  providers.push({
1353
- provide: import_core3.APP_INTERCEPTOR,
1361
+ provide: import_core5.APP_INTERCEPTOR,
1354
1362
  useClass: MessageTenantContextInterceptor
1355
1363
  });
1356
1364
  }
@@ -1362,8 +1370,8 @@ var DatabaseModule = class _DatabaseModule {
1362
1370
  providers,
1363
1371
  exports: [
1364
1372
  TenantDatabaseService,
1365
- TenantContextService2,
1366
- PrimaryDatabaseService2,
1373
+ TenantContextService,
1374
+ PrimaryDatabaseService,
1367
1375
  asyncProvider
1368
1376
  ]
1369
1377
  };
@@ -1378,7 +1386,7 @@ DatabaseModule = _ts_decorate10([
1378
1386
  var import_common13 = require("@nestjs/common");
1379
1387
  var Tenant = (0, import_common13.createParamDecorator)((_data, ctx) => {
1380
1388
  const request = ctx.switchToHttp().getRequest();
1381
- const tenantContext = request.app?.get?.(TenantContextService2);
1389
+ const tenantContext = request.app?.get?.(TenantContextService);
1382
1390
  if (!tenantContext) {
1383
1391
  throw new Error("TenantContextService not found.");
1384
1392
  }
@@ -2540,267 +2548,74 @@ HttpModule = _ts_decorate13([
2540
2548
  (0, import_common37.Module)({
2541
2549
  providers: [
2542
2550
  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
- });
2771
- }
2772
- }
2773
- };
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);
2551
+ ],
2552
+ exports: [
2553
+ CsrfGuard
2554
+ ]
2555
+ })
2556
+ ], HttpModule);
2557
+
2558
+ // src/logger/interceptors/http-logger.interceptor.ts
2559
+ var import_common39 = require("@nestjs/common");
2560
+ var import_operators2 = require("rxjs/operators");
2781
2561
 
2782
2562
  // src/logger/services/logger.service.ts
2783
- var import_common40 = require("@nestjs/common");
2563
+ var import_common38 = require("@nestjs/common");
2784
2564
  var import_winston = require("winston");
2785
2565
  var import_winston_daily_rotate_file = __toESM(require("winston-daily-rotate-file"), 1);
2786
- function _ts_decorate16(decorators, target, key, desc) {
2566
+
2567
+ // src/logger/utils/index.ts
2568
+ var import_node_async_hooks = require("async_hooks");
2569
+ var import_node_crypto = require("crypto");
2570
+ var correlationStorage = new import_node_async_hooks.AsyncLocalStorage();
2571
+ function getCorrelationContext() {
2572
+ return correlationStorage.getStore();
2573
+ }
2574
+ __name(getCorrelationContext, "getCorrelationContext");
2575
+ function runWithCorrelationContext(context, callback) {
2576
+ return correlationStorage.run(context, callback);
2577
+ }
2578
+ __name(runWithCorrelationContext, "runWithCorrelationContext");
2579
+ function updateCorrelationContext(updates) {
2580
+ const context = correlationStorage.getStore();
2581
+ if (context) {
2582
+ Object.assign(context, updates);
2583
+ }
2584
+ }
2585
+ __name(updateCorrelationContext, "updateCorrelationContext");
2586
+ var DEFAULT_CORRELATION_HEADER = "x-correlation-id";
2587
+ function generateCorrelationId() {
2588
+ return (0, import_node_crypto.randomUUID)();
2589
+ }
2590
+ __name(generateCorrelationId, "generateCorrelationId");
2591
+ function addCorrelationIdToResponse(reply, correlationId, headerName = DEFAULT_CORRELATION_HEADER) {
2592
+ if (typeof reply.header === "function") {
2593
+ reply.header(headerName, correlationId);
2594
+ } else if (reply.raw && typeof reply.raw.setHeader === "function") {
2595
+ reply.raw.setHeader(headerName, correlationId);
2596
+ }
2597
+ }
2598
+ __name(addCorrelationIdToResponse, "addCorrelationIdToResponse");
2599
+
2600
+ // src/logger/services/logger.service.ts
2601
+ function _ts_decorate14(decorators, target, key, desc) {
2787
2602
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2788
2603
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2789
2604
  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;
2790
2605
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2791
2606
  }
2792
- __name(_ts_decorate16, "_ts_decorate");
2793
- function _ts_metadata9(k, v) {
2607
+ __name(_ts_decorate14, "_ts_decorate");
2608
+ function _ts_metadata7(k, v) {
2794
2609
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2795
2610
  }
2796
- __name(_ts_metadata9, "_ts_metadata");
2797
- function _ts_param5(paramIndex, decorator) {
2611
+ __name(_ts_metadata7, "_ts_metadata");
2612
+ function _ts_param4(paramIndex, decorator) {
2798
2613
  return function(target, key) {
2799
2614
  decorator(target, key, paramIndex);
2800
2615
  };
2801
2616
  }
2802
- __name(_ts_param5, "_ts_param");
2803
- var LoggerService2 = class _LoggerService {
2617
+ __name(_ts_param4, "_ts_param");
2618
+ var LoggerService = class _LoggerService {
2804
2619
  static {
2805
2620
  __name(this, "LoggerService");
2806
2621
  }
@@ -3001,16 +2816,211 @@ ${trace}`;
3001
2816
  return childLogger;
3002
2817
  }
3003
2818
  };
3004
- LoggerService2 = _ts_decorate16([
2819
+ LoggerService = _ts_decorate14([
2820
+ (0, import_common38.Injectable)(),
2821
+ _ts_param4(0, (0, import_common38.Optional)()),
2822
+ _ts_param4(1, (0, import_common38.Optional)()),
2823
+ _ts_metadata7("design:type", Function),
2824
+ _ts_metadata7("design:paramtypes", [
2825
+ typeof LoggerModuleOptions === "undefined" ? Object : LoggerModuleOptions,
2826
+ typeof Logger === "undefined" ? Object : Logger
2827
+ ])
2828
+ ], LoggerService);
2829
+
2830
+ // src/logger/interceptors/http-logger.interceptor.ts
2831
+ function _ts_decorate15(decorators, target, key, desc) {
2832
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2833
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2834
+ 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;
2835
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2836
+ }
2837
+ __name(_ts_decorate15, "_ts_decorate");
2838
+ function _ts_metadata8(k, v) {
2839
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2840
+ }
2841
+ __name(_ts_metadata8, "_ts_metadata");
2842
+ function _ts_param5(paramIndex, decorator) {
2843
+ return function(target, key) {
2844
+ decorator(target, key, paramIndex);
2845
+ };
2846
+ }
2847
+ __name(_ts_param5, "_ts_param");
2848
+ var HttpLoggerInterceptor = class {
2849
+ static {
2850
+ __name(this, "HttpLoggerInterceptor");
2851
+ }
2852
+ logger;
2853
+ enableRequestLog;
2854
+ enableResponseLog;
2855
+ slowRequestThreshold;
2856
+ constructor(logger, options) {
2857
+ this.logger = logger;
2858
+ this.enableRequestLog = options?.enableRequestLog ?? true;
2859
+ this.enableResponseLog = options?.enableResponseLog ?? true;
2860
+ this.slowRequestThreshold = options?.slowRequestThreshold ?? 3e3;
2861
+ }
2862
+ intercept(context, next) {
2863
+ if (context.getType() !== "http") {
2864
+ return next.handle();
2865
+ }
2866
+ const httpContext = context.switchToHttp();
2867
+ const request = httpContext.getRequest();
2868
+ const response = httpContext.getResponse();
2869
+ const startTime = Date.now();
2870
+ if (this.enableRequestLog) {
2871
+ this.logRequest(request);
2872
+ }
2873
+ return next.handle().pipe((0, import_operators2.tap)(() => {
2874
+ if (this.enableResponseLog) {
2875
+ const duration = Date.now() - startTime;
2876
+ this.logResponse(request, response, duration);
2877
+ }
2878
+ }), (0, import_operators2.catchError)((error) => {
2879
+ const duration = Date.now() - startTime;
2880
+ this.logError(request, response, duration, error);
2881
+ throw error;
2882
+ }));
2883
+ }
2884
+ logRequest(request) {
2885
+ try {
2886
+ const correlationContext = getCorrelationContext();
2887
+ const metadata = {
2888
+ type: "http_request",
2889
+ method: request.method,
2890
+ url: request.url,
2891
+ correlationId: correlationContext?.correlationId,
2892
+ ip: request.ip,
2893
+ userAgent: request.headers["user-agent"]
2894
+ };
2895
+ this.logger.logWithMetadata("log", `Incoming ${request.method} ${request.url}`, metadata);
2896
+ } catch (error) {
2897
+ this.logger.error("Failed to log HTTP request", error.stack);
2898
+ }
2899
+ }
2900
+ logResponse(request, response, duration) {
2901
+ try {
2902
+ const correlationContext = getCorrelationContext();
2903
+ const statusCode = response.statusCode;
2904
+ const logLevel = statusCode >= 500 ? "error" : statusCode >= 400 ? "warn" : "log";
2905
+ const metadata = {
2906
+ type: "http_response",
2907
+ method: request.method,
2908
+ url: request.url,
2909
+ statusCode,
2910
+ duration,
2911
+ correlationId: correlationContext?.correlationId
2912
+ };
2913
+ if (duration > this.slowRequestThreshold) {
2914
+ metadata.slowRequest = true;
2915
+ }
2916
+ const message = metadata.slowRequest ? `SLOW ${request.method} ${request.url} ${statusCode} - ${duration}ms` : `${request.method} ${request.url} ${statusCode} - ${duration}ms`;
2917
+ this.logger.logWithMetadata(logLevel, message, metadata);
2918
+ } catch (error) {
2919
+ this.logger.error("Failed to log HTTP response", error.stack);
2920
+ }
2921
+ }
2922
+ logError(request, response, duration, error) {
2923
+ try {
2924
+ const correlationContext = getCorrelationContext();
2925
+ const statusCode = response.statusCode || 500;
2926
+ const metadata = {
2927
+ type: "http_error",
2928
+ method: request.method,
2929
+ url: request.url,
2930
+ statusCode,
2931
+ duration,
2932
+ correlationId: correlationContext?.correlationId,
2933
+ errorName: error?.name || "Error",
2934
+ errorMessage: error?.message || "Unknown error"
2935
+ };
2936
+ if (error?.stack) {
2937
+ metadata.trace = error.stack;
2938
+ }
2939
+ if (error?.response) {
2940
+ metadata.errorDetails = error.response;
2941
+ }
2942
+ const message = `ERROR ${request.method} ${request.url} ${statusCode} - ${error?.message || "Unknown error"}`;
2943
+ this.logger.logWithMetadata("error", message, metadata);
2944
+ } catch (loggingError) {
2945
+ this.logger.error("Failed to log HTTP error", loggingError.stack);
2946
+ }
2947
+ }
2948
+ };
2949
+ HttpLoggerInterceptor = _ts_decorate15([
2950
+ (0, import_common39.Injectable)(),
2951
+ _ts_param5(1, (0, import_common39.Optional)()),
2952
+ _ts_metadata8("design:type", Function),
2953
+ _ts_metadata8("design:paramtypes", [
2954
+ typeof LoggerService === "undefined" ? Object : LoggerService,
2955
+ typeof HttpLoggerOptions === "undefined" ? Object : HttpLoggerOptions
2956
+ ])
2957
+ ], HttpLoggerInterceptor);
2958
+
2959
+ // src/logger/logger.module.ts
2960
+ var import_common41 = require("@nestjs/common");
2961
+
2962
+ // src/logger/middleware/correlation-id.middleware.ts
2963
+ var import_common40 = require("@nestjs/common");
2964
+ function _ts_decorate16(decorators, target, key, desc) {
2965
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2966
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2967
+ 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;
2968
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2969
+ }
2970
+ __name(_ts_decorate16, "_ts_decorate");
2971
+ function _ts_metadata9(k, v) {
2972
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2973
+ }
2974
+ __name(_ts_metadata9, "_ts_metadata");
2975
+ var CorrelationIdMiddleware = class {
2976
+ static {
2977
+ __name(this, "CorrelationIdMiddleware");
2978
+ }
2979
+ includeInResponse;
2980
+ responseHeader;
2981
+ constructor(options = {}) {
2982
+ this.includeInResponse = options.includeInResponse ?? true;
2983
+ this.responseHeader = options.responseHeader ?? DEFAULT_CORRELATION_HEADER;
2984
+ }
2985
+ /**
2986
+ * Middleware handler for processing requests.
2987
+ */
2988
+ use(_req, reply, next) {
2989
+ const correlationId = generateCorrelationId();
2990
+ if (this.includeInResponse) {
2991
+ addCorrelationIdToResponse(reply, correlationId, this.responseHeader);
2992
+ }
2993
+ runWithCorrelationContext({
2994
+ correlationId
2995
+ }, () => {
2996
+ next();
2997
+ });
2998
+ }
2999
+ /**
3000
+ * Fastify hook handler for onRequest.
3001
+ * This is an async function that returns a Promise, ensuring the AsyncLocalStorage
3002
+ * context persists throughout the entire request lifecycle.
3003
+ */
3004
+ async onRequest(_req, reply) {
3005
+ const correlationId = generateCorrelationId();
3006
+ if (this.includeInResponse) {
3007
+ addCorrelationIdToResponse(reply, correlationId, this.responseHeader);
3008
+ }
3009
+ const store = correlationStorage.getStore();
3010
+ if (!store) {
3011
+ correlationStorage.enterWith({
3012
+ correlationId
3013
+ });
3014
+ }
3015
+ }
3016
+ };
3017
+ CorrelationIdMiddleware = _ts_decorate16([
3005
3018
  (0, import_common40.Injectable)(),
3006
- _ts_param5(0, (0, import_common40.Optional)()),
3007
- _ts_param5(1, (0, import_common40.Optional)()),
3008
3019
  _ts_metadata9("design:type", Function),
3009
3020
  _ts_metadata9("design:paramtypes", [
3010
- typeof LoggerModuleOptions === "undefined" ? Object : LoggerModuleOptions,
3011
- typeof Logger === "undefined" ? Object : Logger
3021
+ typeof CorrelationIdMiddlewareOptions === "undefined" ? Object : CorrelationIdMiddlewareOptions
3012
3022
  ])
3013
- ], LoggerService2);
3023
+ ], CorrelationIdMiddleware);
3014
3024
 
3015
3025
  // src/logger/logger.module.ts
3016
3026
  function _ts_decorate17(decorators, target, key, desc) {
@@ -3133,9 +3143,9 @@ function createLoggerProviders(options = {}) {
3133
3143
  providers.push(createDefaultLoggerProvider(mergedOptions));
3134
3144
  }
3135
3145
  providers.push({
3136
- provide: LoggerService2,
3146
+ provide: LoggerService,
3137
3147
  useFactory: /* @__PURE__ */ __name((opts, defaultLogger) => {
3138
- return new LoggerService2(opts, defaultLogger);
3148
+ return new LoggerService(opts, defaultLogger);
3139
3149
  }, "useFactory"),
3140
3150
  inject: [
3141
3151
  LOGGER_MODULE_OPTIONS,
@@ -3164,7 +3174,7 @@ function createLoggerProviders(options = {}) {
3164
3174
  return new HttpLoggerInterceptor(logger, httpLoggerOptions);
3165
3175
  }, "useFactory"),
3166
3176
  inject: [
3167
- LoggerService2,
3177
+ LoggerService,
3168
3178
  LOGGER_MODULE_OPTIONS
3169
3179
  ]
3170
3180
  });
@@ -3232,7 +3242,7 @@ var LoggerModule = class _LoggerModule {
3232
3242
  module: _LoggerModule,
3233
3243
  providers,
3234
3244
  exports: [
3235
- LoggerService2,
3245
+ LoggerService,
3236
3246
  CorrelationIdMiddleware,
3237
3247
  HttpLoggerInterceptor,
3238
3248
  LOGGER_MODULE_OPTIONS
@@ -3309,9 +3319,9 @@ var LoggerModule = class _LoggerModule {
3309
3319
  },
3310
3320
  // Unified logger service
3311
3321
  {
3312
- provide: LoggerService2,
3322
+ provide: LoggerService,
3313
3323
  useFactory: /* @__PURE__ */ __name((opts, defaultLogger) => {
3314
- return new LoggerService2(opts, defaultLogger);
3324
+ return new LoggerService(opts, defaultLogger);
3315
3325
  }, "useFactory"),
3316
3326
  inject: [
3317
3327
  LOGGER_MODULE_OPTIONS,
@@ -3342,13 +3352,13 @@ var LoggerModule = class _LoggerModule {
3342
3352
  return new HttpLoggerInterceptor(logger, httpLoggerOptions);
3343
3353
  }, "useFactory"),
3344
3354
  inject: [
3345
- LoggerService2,
3355
+ LoggerService,
3346
3356
  LOGGER_MODULE_OPTIONS
3347
3357
  ]
3348
3358
  }
3349
3359
  ],
3350
3360
  exports: [
3351
- LoggerService2,
3361
+ LoggerService,
3352
3362
  CorrelationIdMiddleware,
3353
3363
  HttpLoggerInterceptor,
3354
3364
  LOGGER_MODULE_OPTIONS