@vritti/api-sdk 0.0.3 → 0.0.6

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.js CHANGED
@@ -334,16 +334,15 @@ var PrimaryDatabaseService = class _PrimaryDatabaseService {
334
334
  this.logger.log(`Cleared ${size} cached tenant configs`);
335
335
  }
336
336
  /**
337
- * Get primary database client for direct database access
338
- *
339
- * This is useful for platform admin operations (creating tenants, billing, etc.)
337
+ * Get the Prisma client for the primary database.
338
+ * This is a synchronous property that returns the initialized Prisma client.
340
339
  *
341
340
  * @returns Primary database client instance
342
341
  * @throws Error if primary database client is not initialized
343
342
  */
344
- getPrimaryDbClient() {
343
+ get prismaClient() {
345
344
  if (!this.primaryDbClient) {
346
- throw new Error("Primary database client not initialized. Are you in gateway mode?");
345
+ throw new Error("Primary database client not initialized");
347
346
  }
348
347
  return this.primaryDbClient;
349
348
  }
@@ -822,6 +821,7 @@ MessageTenantContextInterceptor = _ts_decorate7([
822
821
 
823
822
  // src/database/interceptors/tenant-context.interceptor.ts
824
823
  import { Injectable as Injectable6, Logger as Logger4, Scope as Scope5, UnauthorizedException as UnauthorizedException3 } from "@nestjs/common";
824
+ import { Reflector as Reflector2 } from "@nestjs/core";
825
825
  function _ts_decorate8(decorators, target, key, desc) {
826
826
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
827
827
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -837,11 +837,13 @@ var TenantContextInterceptor = class _TenantContextInterceptor {
837
837
  static {
838
838
  __name(this, "TenantContextInterceptor");
839
839
  }
840
+ reflector;
840
841
  tenantContext;
841
842
  primaryDatabase;
842
843
  requestService;
843
844
  logger = new Logger4(_TenantContextInterceptor.name);
844
- constructor(tenantContext, primaryDatabase, requestService) {
845
+ constructor(reflector, tenantContext, primaryDatabase, requestService) {
846
+ this.reflector = reflector;
845
847
  this.tenantContext = tenantContext;
846
848
  this.primaryDatabase = primaryDatabase;
847
849
  this.requestService = requestService;
@@ -849,8 +851,16 @@ var TenantContextInterceptor = class _TenantContextInterceptor {
849
851
  async intercept(context, next) {
850
852
  const request = context.switchToHttp().getRequest();
851
853
  this.logger.debug(`Processing request: ${request.method} ${request.url}`);
854
+ const isPublic = this.reflector.getAllAndOverride("isPublic", [
855
+ context.getHandler(),
856
+ context.getClass()
857
+ ]);
852
858
  try {
853
859
  const tenantIdentifier = this.requestService.getTenantIdentifier();
860
+ if (isPublic && !tenantIdentifier) {
861
+ this.logger.debug("Public endpoint without tenant identifier, skipping tenant context setup");
862
+ return next.handle();
863
+ }
854
864
  if (!tenantIdentifier) {
855
865
  throw new UnauthorizedException3("Tenant identifier not found in request");
856
866
  }
@@ -885,6 +895,7 @@ TenantContextInterceptor = _ts_decorate8([
885
895
  }),
886
896
  _ts_metadata5("design:type", Function),
887
897
  _ts_metadata5("design:paramtypes", [
898
+ typeof Reflector2 === "undefined" ? Object : Reflector2,
888
899
  typeof TenantContextService === "undefined" ? Object : TenantContextService,
889
900
  typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
890
901
  typeof RequestService === "undefined" ? Object : RequestService
@@ -929,6 +940,17 @@ var TenantDatabaseService = class _TenantDatabaseService {
929
940
  this.startConnectionCleaner();
930
941
  }
931
942
  /**
943
+ * Get the Prisma client for the current tenant's database.
944
+ * This returns the tenant-scoped database client.
945
+ *
946
+ * @returns Tenant-scoped database client instance
947
+ * @throws UnauthorizedException if tenant context not set
948
+ * @throws InternalServerErrorException if connection fails
949
+ */
950
+ get prismaClient() {
951
+ return this.getDbClient();
952
+ }
953
+ /**
932
954
  * Get tenant-scoped database client for the current request/message
933
955
  *
934
956
  * This method:
@@ -1122,7 +1144,7 @@ var DatabaseModule = class _DatabaseModule {
1122
1144
  * })
1123
1145
  */
1124
1146
  static forServer(options) {
1125
- return this.createDynamicModule(options, "gateway");
1147
+ return this.createDynamicModule(options, "server");
1126
1148
  }
1127
1149
  /**
1128
1150
  * Configure DatabaseModule for Microservice/Messaging mode (RabbitMQ workers)
@@ -1165,7 +1187,7 @@ var DatabaseModule = class _DatabaseModule {
1165
1187
  PrimaryDatabaseService,
1166
1188
  TenantDatabaseService
1167
1189
  ];
1168
- if (mode === "gateway") {
1190
+ if (mode === "server") {
1169
1191
  providers.push({
1170
1192
  provide: APP_INTERCEPTOR,
1171
1193
  useClass: TenantContextInterceptor
@@ -1196,6 +1218,545 @@ DatabaseModule = _ts_decorate10([
1196
1218
  Module3({})
1197
1219
  ], DatabaseModule);
1198
1220
 
1221
+ // src/database/repositories/primary-base.repository.ts
1222
+ import { Logger as Logger6 } from "@nestjs/common";
1223
+ var PrimaryBaseRepository = class {
1224
+ static {
1225
+ __name(this, "PrimaryBaseRepository");
1226
+ }
1227
+ database;
1228
+ logger;
1229
+ modelGetter;
1230
+ /**
1231
+ * Lazy getter for Prisma client.
1232
+ * Accesses the client from the database service only when needed,
1233
+ * avoiding initialization timing issues with NestJS lifecycle.
1234
+ */
1235
+ get prisma() {
1236
+ return this.database.prismaClient;
1237
+ }
1238
+ /**
1239
+ * Lazy getter for the Prisma model delegate.
1240
+ * Returns the specific model (e.g., prisma.user, prisma.tenant) for this repository.
1241
+ */
1242
+ get model() {
1243
+ return this.modelGetter(this.prisma);
1244
+ }
1245
+ /**
1246
+ * Create a new repository instance
1247
+ *
1248
+ * @param database - The primary database service
1249
+ * @param getModel - Function that returns the Prisma model delegate from the client
1250
+ *
1251
+ * @example
1252
+ * ```typescript
1253
+ * // Standard usage with full parameter name
1254
+ * constructor(database: PrimaryDatabaseService) {
1255
+ * super(database, (prisma) => prisma.user);
1256
+ * }
1257
+ *
1258
+ * // Short syntax
1259
+ * constructor(database: PrimaryDatabaseService) {
1260
+ * super(database, (p) => p.user);
1261
+ * }
1262
+ *
1263
+ * // Complex model names
1264
+ * constructor(database: PrimaryDatabaseService) {
1265
+ * super(database, (p) => p.emailVerification);
1266
+ * }
1267
+ * ```
1268
+ */
1269
+ constructor(database, getModel) {
1270
+ this.database = database;
1271
+ this.logger = new Logger6(this.constructor.name);
1272
+ this.modelGetter = getModel;
1273
+ this.logger.debug(`Initialized ${this.constructor.name}`);
1274
+ }
1275
+ /**
1276
+ * Create a new record
1277
+ *
1278
+ * @param data - The data to create the record with
1279
+ * @returns Promise resolving to the created record
1280
+ *
1281
+ * @example
1282
+ * ```typescript
1283
+ * const user = await userRepository.create({
1284
+ * email: 'user@example.com',
1285
+ * name: 'John Doe'
1286
+ * });
1287
+ * ```
1288
+ */
1289
+ async create(data) {
1290
+ this.logger.log("Creating record");
1291
+ return await this.model.create({
1292
+ data
1293
+ });
1294
+ }
1295
+ /**
1296
+ * Find a single record by ID
1297
+ *
1298
+ * @param id - The record ID
1299
+ * @returns Promise resolving to the record or null if not found
1300
+ *
1301
+ * @example
1302
+ * ```typescript
1303
+ * const user = await userRepository.findById('user-id-123');
1304
+ * ```
1305
+ */
1306
+ async findById(id) {
1307
+ this.logger.debug(`Finding record by ID: ${id}`);
1308
+ return await this.model.findUnique({
1309
+ where: {
1310
+ id
1311
+ }
1312
+ });
1313
+ }
1314
+ /**
1315
+ * Find a single record with custom where clause
1316
+ *
1317
+ * @param where - The where clause or findUnique args
1318
+ * @returns Promise resolving to the record or null if not found
1319
+ *
1320
+ * @example
1321
+ * ```typescript
1322
+ * // Simple where clause
1323
+ * const user = await userRepository.findOne({ email: 'user@example.com' });
1324
+ *
1325
+ * // With include
1326
+ * const user = await userRepository.findOne({
1327
+ * where: { email: 'user@example.com' },
1328
+ * include: { posts: true }
1329
+ * });
1330
+ * ```
1331
+ */
1332
+ async findOne(where) {
1333
+ this.logger.debug("Finding record with custom query");
1334
+ return await this.model.findUnique(typeof where === "object" && "where" in where ? where : {
1335
+ where
1336
+ });
1337
+ }
1338
+ /**
1339
+ * Find multiple records
1340
+ *
1341
+ * @param args - Prisma findMany arguments (where, orderBy, take, skip, etc.)
1342
+ * @returns Promise resolving to an array of records
1343
+ *
1344
+ * @example
1345
+ * ```typescript
1346
+ * // Find all users
1347
+ * const users = await userRepository.findMany();
1348
+ *
1349
+ * // Find with filtering and pagination
1350
+ * const users = await userRepository.findMany({
1351
+ * where: { status: 'ACTIVE' },
1352
+ * orderBy: { createdAt: 'desc' },
1353
+ * take: 10,
1354
+ * skip: 0
1355
+ * });
1356
+ * ```
1357
+ */
1358
+ async findMany(args) {
1359
+ this.logger.debug("Finding multiple records");
1360
+ return await this.model.findMany(args);
1361
+ }
1362
+ /**
1363
+ * Update a record by ID
1364
+ *
1365
+ * @param id - The record ID
1366
+ * @param data - The data to update
1367
+ * @returns Promise resolving to the updated record
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * const user = await userRepository.update('user-id-123', {
1372
+ * name: 'Jane Doe'
1373
+ * });
1374
+ * ```
1375
+ */
1376
+ async update(id, data) {
1377
+ this.logger.log(`Updating record with ID: ${id}`);
1378
+ return await this.model.update({
1379
+ where: {
1380
+ id
1381
+ },
1382
+ data
1383
+ });
1384
+ }
1385
+ /**
1386
+ * Update multiple records
1387
+ *
1388
+ * @param where - The where clause to match records
1389
+ * @param data - The data to update
1390
+ * @returns Promise resolving to the count of updated records
1391
+ *
1392
+ * @example
1393
+ * ```typescript
1394
+ * const result = await userRepository.updateMany(
1395
+ * { status: 'PENDING' },
1396
+ * { status: 'ACTIVE' }
1397
+ * );
1398
+ * console.log(`Updated ${result.count} users`);
1399
+ * ```
1400
+ */
1401
+ async updateMany(where, data) {
1402
+ this.logger.log("Updating multiple records");
1403
+ return await this.model.updateMany({
1404
+ where,
1405
+ data
1406
+ });
1407
+ }
1408
+ /**
1409
+ * Delete a record by ID
1410
+ *
1411
+ * @param id - The record ID
1412
+ * @returns Promise resolving to the deleted record
1413
+ *
1414
+ * @example
1415
+ * ```typescript
1416
+ * const user = await userRepository.delete('user-id-123');
1417
+ * ```
1418
+ */
1419
+ async delete(id) {
1420
+ this.logger.log(`Deleting record with ID: ${id}`);
1421
+ return await this.model.delete({
1422
+ where: {
1423
+ id
1424
+ }
1425
+ });
1426
+ }
1427
+ /**
1428
+ * Delete multiple records
1429
+ *
1430
+ * @param where - The where clause to match records
1431
+ * @returns Promise resolving to the count of deleted records
1432
+ *
1433
+ * @example
1434
+ * ```typescript
1435
+ * const result = await userRepository.deleteMany({
1436
+ * status: 'INACTIVE',
1437
+ * createdAt: { lt: new Date('2020-01-01') }
1438
+ * });
1439
+ * console.log(`Deleted ${result.count} users`);
1440
+ * ```
1441
+ */
1442
+ async deleteMany(where) {
1443
+ this.logger.log("Deleting multiple records");
1444
+ return await this.model.deleteMany({
1445
+ where
1446
+ });
1447
+ }
1448
+ /**
1449
+ * Count records
1450
+ *
1451
+ * @param where - Optional where clause to filter records
1452
+ * @returns Promise resolving to the count of records
1453
+ *
1454
+ * @example
1455
+ * ```typescript
1456
+ * // Count all users
1457
+ * const total = await userRepository.count();
1458
+ *
1459
+ * // Count active users
1460
+ * const activeCount = await userRepository.count({ status: 'ACTIVE' });
1461
+ * ```
1462
+ */
1463
+ async count(where) {
1464
+ this.logger.debug("Counting records");
1465
+ return await this.model.count({
1466
+ where
1467
+ });
1468
+ }
1469
+ /**
1470
+ * Check if a record exists
1471
+ *
1472
+ * @param where - The where clause to match records
1473
+ * @returns Promise resolving to true if at least one record exists, false otherwise
1474
+ *
1475
+ * @example
1476
+ * ```typescript
1477
+ * const emailExists = await userRepository.exists({
1478
+ * email: 'user@example.com'
1479
+ * });
1480
+ * ```
1481
+ */
1482
+ async exists(where) {
1483
+ const count = await this.model.count({
1484
+ where
1485
+ });
1486
+ return count > 0;
1487
+ }
1488
+ };
1489
+
1490
+ // src/database/repositories/tenant-base.repository.ts
1491
+ import { Logger as Logger7 } from "@nestjs/common";
1492
+ var TenantBaseRepository = class {
1493
+ static {
1494
+ __name(this, "TenantBaseRepository");
1495
+ }
1496
+ database;
1497
+ logger;
1498
+ modelGetter;
1499
+ /**
1500
+ * Lazy getter for Prisma client.
1501
+ * Accesses the client from the database service only when needed,
1502
+ * avoiding initialization timing issues with NestJS lifecycle.
1503
+ */
1504
+ get prisma() {
1505
+ return this.database.prismaClient;
1506
+ }
1507
+ /**
1508
+ * Lazy getter for the Prisma model delegate.
1509
+ * Returns the specific model (e.g., prisma.product, prisma.order) for this repository.
1510
+ */
1511
+ get model() {
1512
+ return this.modelGetter(this.prisma);
1513
+ }
1514
+ /**
1515
+ * Create a new repository instance
1516
+ *
1517
+ * @param database - The tenant database service
1518
+ * @param getModel - Function that returns the Prisma model delegate from the client
1519
+ *
1520
+ * @example
1521
+ * ```typescript
1522
+ * // Standard usage with full parameter name
1523
+ * constructor(database: TenantDatabaseService) {
1524
+ * super(database, (prisma) => prisma.product);
1525
+ * }
1526
+ *
1527
+ * // Short syntax
1528
+ * constructor(database: TenantDatabaseService) {
1529
+ * super(database, (p) => p.product);
1530
+ * }
1531
+ *
1532
+ * // Complex model names
1533
+ * constructor(database: TenantDatabaseService) {
1534
+ * super(database, (p) => p.inventoryItem);
1535
+ * }
1536
+ * ```
1537
+ */
1538
+ constructor(database, getModel) {
1539
+ this.database = database;
1540
+ this.logger = new Logger7(this.constructor.name);
1541
+ this.modelGetter = getModel;
1542
+ this.logger.debug(`Initialized ${this.constructor.name}`);
1543
+ }
1544
+ /**
1545
+ * Create a new record
1546
+ *
1547
+ * @param data - The data to create the record with
1548
+ * @returns Promise resolving to the created record
1549
+ *
1550
+ * @example
1551
+ * ```typescript
1552
+ * const product = await productRepository.create({
1553
+ * name: 'Widget',
1554
+ * sku: 'WDG-001',
1555
+ * price: 9.99
1556
+ * });
1557
+ * ```
1558
+ */
1559
+ async create(data) {
1560
+ this.logger.log("Creating record");
1561
+ return await this.model.create({
1562
+ data
1563
+ });
1564
+ }
1565
+ /**
1566
+ * Find a single record by ID
1567
+ *
1568
+ * @param id - The record ID
1569
+ * @returns Promise resolving to the record or null if not found
1570
+ *
1571
+ * @example
1572
+ * ```typescript
1573
+ * const product = await productRepository.findById('product-id-123');
1574
+ * ```
1575
+ */
1576
+ async findById(id) {
1577
+ this.logger.debug(`Finding record by ID: ${id}`);
1578
+ return await this.model.findUnique({
1579
+ where: {
1580
+ id
1581
+ }
1582
+ });
1583
+ }
1584
+ /**
1585
+ * Find a single record with custom where clause
1586
+ *
1587
+ * @param where - The where clause or findUnique args
1588
+ * @returns Promise resolving to the record or null if not found
1589
+ *
1590
+ * @example
1591
+ * ```typescript
1592
+ * // Simple where clause
1593
+ * const product = await productRepository.findOne({ sku: 'WDG-001' });
1594
+ *
1595
+ * // With include
1596
+ * const product = await productRepository.findOne({
1597
+ * where: { sku: 'WDG-001' },
1598
+ * include: { category: true }
1599
+ * });
1600
+ * ```
1601
+ */
1602
+ async findOne(where) {
1603
+ this.logger.debug("Finding record with custom query");
1604
+ return await this.model.findUnique(typeof where === "object" && "where" in where ? where : {
1605
+ where
1606
+ });
1607
+ }
1608
+ /**
1609
+ * Find multiple records
1610
+ *
1611
+ * @param args - Prisma findMany arguments (where, orderBy, take, skip, etc.)
1612
+ * @returns Promise resolving to an array of records
1613
+ *
1614
+ * @example
1615
+ * ```typescript
1616
+ * // Find all products
1617
+ * const products = await productRepository.findMany();
1618
+ *
1619
+ * // Find with filtering and pagination
1620
+ * const products = await productRepository.findMany({
1621
+ * where: { status: 'ACTIVE' },
1622
+ * orderBy: { createdAt: 'desc' },
1623
+ * take: 10,
1624
+ * skip: 0
1625
+ * });
1626
+ * ```
1627
+ */
1628
+ async findMany(args) {
1629
+ this.logger.debug("Finding multiple records");
1630
+ return await this.model.findMany(args);
1631
+ }
1632
+ /**
1633
+ * Update a record by ID
1634
+ *
1635
+ * @param id - The record ID
1636
+ * @param data - The data to update
1637
+ * @returns Promise resolving to the updated record
1638
+ *
1639
+ * @example
1640
+ * ```typescript
1641
+ * const product = await productRepository.update('product-id-123', {
1642
+ * price: 12.99
1643
+ * });
1644
+ * ```
1645
+ */
1646
+ async update(id, data) {
1647
+ this.logger.log(`Updating record with ID: ${id}`);
1648
+ return await this.model.update({
1649
+ where: {
1650
+ id
1651
+ },
1652
+ data
1653
+ });
1654
+ }
1655
+ /**
1656
+ * Update multiple records
1657
+ *
1658
+ * @param where - The where clause to match records
1659
+ * @param data - The data to update
1660
+ * @returns Promise resolving to the count of updated records
1661
+ *
1662
+ * @example
1663
+ * ```typescript
1664
+ * const result = await productRepository.updateMany(
1665
+ * { status: 'PENDING' },
1666
+ * { status: 'ACTIVE' }
1667
+ * );
1668
+ * console.log(`Updated ${result.count} products`);
1669
+ * ```
1670
+ */
1671
+ async updateMany(where, data) {
1672
+ this.logger.log("Updating multiple records");
1673
+ return await this.model.updateMany({
1674
+ where,
1675
+ data
1676
+ });
1677
+ }
1678
+ /**
1679
+ * Delete a record by ID
1680
+ *
1681
+ * @param id - The record ID
1682
+ * @returns Promise resolving to the deleted record
1683
+ *
1684
+ * @example
1685
+ * ```typescript
1686
+ * const product = await productRepository.delete('product-id-123');
1687
+ * ```
1688
+ */
1689
+ async delete(id) {
1690
+ this.logger.log(`Deleting record with ID: ${id}`);
1691
+ return await this.model.delete({
1692
+ where: {
1693
+ id
1694
+ }
1695
+ });
1696
+ }
1697
+ /**
1698
+ * Delete multiple records
1699
+ *
1700
+ * @param where - The where clause to match records
1701
+ * @returns Promise resolving to the count of deleted records
1702
+ *
1703
+ * @example
1704
+ * ```typescript
1705
+ * const result = await productRepository.deleteMany({
1706
+ * status: 'INACTIVE',
1707
+ * createdAt: { lt: new Date('2020-01-01') }
1708
+ * });
1709
+ * console.log(`Deleted ${result.count} products`);
1710
+ * ```
1711
+ */
1712
+ async deleteMany(where) {
1713
+ this.logger.log("Deleting multiple records");
1714
+ return await this.model.deleteMany({
1715
+ where
1716
+ });
1717
+ }
1718
+ /**
1719
+ * Count records
1720
+ *
1721
+ * @param where - Optional where clause to filter records
1722
+ * @returns Promise resolving to the count of records
1723
+ *
1724
+ * @example
1725
+ * ```typescript
1726
+ * // Count all products
1727
+ * const total = await productRepository.count();
1728
+ *
1729
+ * // Count active products
1730
+ * const activeCount = await productRepository.count({ status: 'ACTIVE' });
1731
+ * ```
1732
+ */
1733
+ async count(where) {
1734
+ this.logger.debug("Counting records");
1735
+ return await this.model.count({
1736
+ where
1737
+ });
1738
+ }
1739
+ /**
1740
+ * Check if a record exists
1741
+ *
1742
+ * @param where - The where clause to match records
1743
+ * @returns Promise resolving to true if at least one record exists, false otherwise
1744
+ *
1745
+ * @example
1746
+ * ```typescript
1747
+ * const skuExists = await productRepository.exists({
1748
+ * sku: 'WDG-001'
1749
+ * });
1750
+ * ```
1751
+ */
1752
+ async exists(where) {
1753
+ const count = await this.model.count({
1754
+ where
1755
+ });
1756
+ return count > 0;
1757
+ }
1758
+ };
1759
+
1199
1760
  // src/database/decorators/tenant.decorator.ts
1200
1761
  import { createParamDecorator } from "@nestjs/common";
1201
1762
  var Tenant = createParamDecorator((data, ctx) => {
@@ -1214,13 +1775,232 @@ var Onboarding = /* @__PURE__ */ __name(() => SetMetadata("isOnboarding", true),
1214
1775
  // src/auth/decorators/public.decorator.ts
1215
1776
  import { SetMetadata as SetMetadata2 } from "@nestjs/common";
1216
1777
  var Public = /* @__PURE__ */ __name(() => SetMetadata2("isPublic", true), "Public");
1778
+
1779
+ // src/http/http.module.ts
1780
+ import { Module as Module4 } from "@nestjs/common";
1781
+
1782
+ // src/http/guards/csrf.guard.ts
1783
+ import { ForbiddenException, Injectable as Injectable8, Logger as Logger8 } from "@nestjs/common";
1784
+ import { Reflector as Reflector3 } from "@nestjs/core";
1785
+ function _ts_decorate11(decorators, target, key, desc) {
1786
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1787
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1788
+ 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;
1789
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1790
+ }
1791
+ __name(_ts_decorate11, "_ts_decorate");
1792
+ function _ts_metadata7(k, v) {
1793
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1794
+ }
1795
+ __name(_ts_metadata7, "_ts_metadata");
1796
+ var CsrfGuard = class _CsrfGuard {
1797
+ static {
1798
+ __name(this, "CsrfGuard");
1799
+ }
1800
+ reflector;
1801
+ logger = new Logger8(_CsrfGuard.name);
1802
+ constructor(reflector) {
1803
+ this.reflector = reflector;
1804
+ }
1805
+ async canActivate(context) {
1806
+ const request = context.switchToHttp().getRequest();
1807
+ const reply = context.switchToHttp().getResponse();
1808
+ const safeMethods = [
1809
+ "GET",
1810
+ "HEAD",
1811
+ "OPTIONS"
1812
+ ];
1813
+ if (safeMethods.includes(request.method)) {
1814
+ return true;
1815
+ }
1816
+ try {
1817
+ const fastifyInstance = request.server;
1818
+ if (!fastifyInstance.csrfProtection) {
1819
+ this.logger.error("CSRF protection plugin not found. Ensure @fastify/csrf-protection is registered.");
1820
+ throw new ForbiddenException("CSRF protection not configured");
1821
+ }
1822
+ await new Promise((resolve, reject) => {
1823
+ fastifyInstance.csrfProtection(request, reply, (err) => {
1824
+ if (err) {
1825
+ reject(err);
1826
+ } else {
1827
+ resolve();
1828
+ }
1829
+ });
1830
+ });
1831
+ this.logger.debug(`CSRF validation successful for ${request.method} ${request.url}`);
1832
+ return true;
1833
+ } catch (error) {
1834
+ this.logger.warn(`CSRF validation failed for ${request.method} ${request.url}: ${error instanceof Error ? error.message : "Unknown error"}`);
1835
+ throw new ForbiddenException({
1836
+ errors: [
1837
+ {
1838
+ field: "csrf",
1839
+ message: "Invalid or missing CSRF token"
1840
+ }
1841
+ ],
1842
+ message: "CSRF validation failed"
1843
+ });
1844
+ }
1845
+ }
1846
+ };
1847
+ CsrfGuard = _ts_decorate11([
1848
+ Injectable8(),
1849
+ _ts_metadata7("design:type", Function),
1850
+ _ts_metadata7("design:paramtypes", [
1851
+ typeof Reflector3 === "undefined" ? Object : Reflector3
1852
+ ])
1853
+ ], CsrfGuard);
1854
+
1855
+ // src/http/http.module.ts
1856
+ function _ts_decorate12(decorators, target, key, desc) {
1857
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1858
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1859
+ 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;
1860
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1861
+ }
1862
+ __name(_ts_decorate12, "_ts_decorate");
1863
+ var HttpModule = class {
1864
+ static {
1865
+ __name(this, "HttpModule");
1866
+ }
1867
+ };
1868
+ HttpModule = _ts_decorate12([
1869
+ Module4({
1870
+ providers: [
1871
+ CsrfGuard
1872
+ ],
1873
+ exports: [
1874
+ CsrfGuard
1875
+ ]
1876
+ })
1877
+ ], HttpModule);
1878
+
1879
+ // src/http/filters/http-exception.filter.ts
1880
+ import { Catch, HttpException, HttpStatus, Logger as Logger9 } from "@nestjs/common";
1881
+ function _ts_decorate13(decorators, target, key, desc) {
1882
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1883
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1884
+ 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;
1885
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1886
+ }
1887
+ __name(_ts_decorate13, "_ts_decorate");
1888
+ var HttpExceptionFilter = class _HttpExceptionFilter {
1889
+ static {
1890
+ __name(this, "HttpExceptionFilter");
1891
+ }
1892
+ logger = new Logger9(_HttpExceptionFilter.name);
1893
+ catch(exception, host) {
1894
+ const ctx = host.switchToHttp();
1895
+ const reply = ctx.getResponse();
1896
+ const request = ctx.getRequest();
1897
+ let status = HttpStatus.INTERNAL_SERVER_ERROR;
1898
+ let errors = [];
1899
+ let message;
1900
+ if (exception instanceof HttpException) {
1901
+ status = exception.getStatus();
1902
+ const exceptionResponse = exception.getResponse();
1903
+ if (typeof exceptionResponse === "object" && exceptionResponse !== null) {
1904
+ const responseObj = exceptionResponse;
1905
+ if (Array.isArray(responseObj.message)) {
1906
+ errors = this.parseValidationErrors(responseObj.message);
1907
+ message = "Validation failed";
1908
+ } else if (responseObj.message) {
1909
+ errors = [
1910
+ {
1911
+ field: "general",
1912
+ message: responseObj.message
1913
+ }
1914
+ ];
1915
+ message = responseObj.message;
1916
+ }
1917
+ } else if (typeof exceptionResponse === "string") {
1918
+ errors = [
1919
+ {
1920
+ field: "general",
1921
+ message: exceptionResponse
1922
+ }
1923
+ ];
1924
+ message = exceptionResponse;
1925
+ }
1926
+ } else if (exception instanceof Error) {
1927
+ this.logger.error(`Unhandled error: ${exception.message}`, exception.stack);
1928
+ errors = [
1929
+ {
1930
+ field: "general",
1931
+ message: "Internal server error"
1932
+ }
1933
+ ];
1934
+ message = "An unexpected error occurred";
1935
+ } else {
1936
+ this.logger.error("Unknown exception type", exception);
1937
+ errors = [
1938
+ {
1939
+ field: "general",
1940
+ message: "Internal server error"
1941
+ }
1942
+ ];
1943
+ message = "An unexpected error occurred";
1944
+ }
1945
+ const errorResponse = {
1946
+ errors,
1947
+ message,
1948
+ statusCode: status,
1949
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1950
+ path: request.url
1951
+ };
1952
+ if (status >= 500) {
1953
+ this.logger.error(`HTTP ${status} Error: ${JSON.stringify(errorResponse)}`, exception instanceof Error ? exception.stack : void 0);
1954
+ } else {
1955
+ this.logger.warn(`HTTP ${status} Error: ${JSON.stringify(errorResponse)}`);
1956
+ }
1957
+ reply.status(status).send(errorResponse);
1958
+ }
1959
+ /**
1960
+ * Parse class-validator error messages into field-specific errors
1961
+ */
1962
+ parseValidationErrors(messages) {
1963
+ const errors = [];
1964
+ for (const msg of messages) {
1965
+ if (typeof msg === "string") {
1966
+ errors.push({
1967
+ field: "general",
1968
+ message: msg
1969
+ });
1970
+ } else if (typeof msg === "object" && msg.property && msg.constraints) {
1971
+ const field = msg.property;
1972
+ const constraintMessages = Object.values(msg.constraints);
1973
+ for (const constraintMsg of constraintMessages) {
1974
+ errors.push({
1975
+ field,
1976
+ message: constraintMsg
1977
+ });
1978
+ }
1979
+ }
1980
+ }
1981
+ return errors.length > 0 ? errors : [
1982
+ {
1983
+ field: "general",
1984
+ message: "Validation failed"
1985
+ }
1986
+ ];
1987
+ }
1988
+ };
1989
+ HttpExceptionFilter = _ts_decorate13([
1990
+ Catch()
1991
+ ], HttpExceptionFilter);
1217
1992
  export {
1218
1993
  AuthConfigModule,
1994
+ CsrfGuard,
1219
1995
  DatabaseModule,
1996
+ HttpExceptionFilter,
1997
+ HttpModule,
1220
1998
  Onboarding,
1999
+ PrimaryBaseRepository,
1221
2000
  PrimaryDatabaseService,
1222
2001
  Public,
1223
2002
  Tenant,
2003
+ TenantBaseRepository,
1224
2004
  TenantContextService,
1225
2005
  TenantDatabaseService,
1226
2006
  VrittiAuthGuard