@vritti/api-sdk 0.2.3 → 0.2.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
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc2) => {
18
18
  }
19
19
  return to;
20
20
  };
21
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
22
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
23
  // If the importer is in node compatibility mode or this is not an ESM
23
24
  // file that has been converted to a CommonJS file using a Babel-
@@ -41,7 +42,13 @@ __export(index_exports, {
41
42
  ConflictException: () => ConflictException,
42
43
  CookieDomain: () => CookieDomain,
43
44
  CorrelationIdMiddleware: () => CorrelationIdMiddleware,
45
+ CreateDataTableViewDto: () => CreateDataTableViewDto,
46
+ DATA_TABLE_VIEWS_TABLE: () => DATA_TABLE_VIEWS_TABLE,
44
47
  DEFAULT_CORRELATION_HEADER: () => DEFAULT_CORRELATION_HEADER,
48
+ DataTableModule: () => DataTableModule,
49
+ DataTableStateService: () => DataTableStateService,
50
+ DataTableViewDto: () => DataTableViewDto,
51
+ DataTableViewsService: () => DataTableViewsService,
45
52
  DatabaseModule: () => DatabaseModule,
46
53
  EmailModule: () => EmailModule,
47
54
  EmailService: () => EmailService,
@@ -69,6 +76,7 @@ __export(index_exports, {
69
76
  RedisCacheProvider: () => RedisCacheProvider,
70
77
  RefreshCookieOptions: () => RefreshCookieOptions,
71
78
  RefreshTokenCookie: () => RefreshTokenCookie,
79
+ RenameDataTableViewDto: () => RenameDataTableViewDto,
72
80
  RequestTimeoutException: () => RequestTimeoutException,
73
81
  Reset: () => Reset,
74
82
  RootModule: () => RootModule,
@@ -83,17 +91,22 @@ __export(index_exports, {
83
91
  TenantBaseRepository: () => TenantBaseRepository,
84
92
  TenantContextService: () => TenantContextService,
85
93
  TenantDatabaseService: () => TenantDatabaseService,
94
+ ToggleShareDataTableViewDto: () => ToggleShareDataTableViewDto,
86
95
  TokenType: () => TokenType,
87
96
  TooManyRequestsException: () => TooManyRequestsException,
88
97
  UnauthorizedException: () => UnauthorizedException,
89
98
  UnprocessableEntityException: () => UnprocessableEntityException,
90
99
  UnsupportedMediaTypeException: () => UnsupportedMediaTypeException,
100
+ UpdateDataTableViewDto: () => UpdateDataTableViewDto,
101
+ UpsertDataTableStateDto: () => UpsertDataTableStateDto,
91
102
  UserId: () => UserId,
92
103
  ValidationException: () => ValidationException,
93
104
  VrittiAuthGuard: () => VrittiAuthGuard,
94
105
  addCorrelationIdToResponse: () => addCorrelationIdToResponse,
95
106
  configureApiSdk: () => configureApiSdk,
96
107
  correlationStorage: () => correlationStorage,
108
+ dataTableViewsColumns: () => dataTableViewsColumns,
109
+ dataTableViewsIndexes: () => dataTableViewsIndexes,
97
110
  defineConfig: () => defineConfig,
98
111
  extractCountryFromPhone: () => extractCountryFromPhone,
99
112
  generateCorrelationId: () => generateCorrelationId,
@@ -1285,10 +1298,21 @@ var PrimaryDatabaseService = class _PrimaryDatabaseService {
1285
1298
  // Initializes connection to primary database using Drizzle
1286
1299
  async initializeDrizzleClient() {
1287
1300
  try {
1288
- const databaseUrl = this.buildPrimaryDbUrl();
1301
+ const { host, port = 5432, username, password, database, schema, sslMode = "require" } = this.options.primaryDb;
1289
1302
  this.pool = new import_pg.Pool({
1290
- connectionString: databaseUrl,
1291
- max: this.options.maxConnections || 10
1303
+ host,
1304
+ port,
1305
+ user: username,
1306
+ password,
1307
+ database,
1308
+ max: this.options.maxConnections || 10,
1309
+ ssl: sslMode === "disable" ? false : {
1310
+ rejectUnauthorized: sslMode !== "no-verify"
1311
+ },
1312
+ // Pass schema as a PostgreSQL startup option — recognized by node-postgres, unlike the ?schema= URL param
1313
+ ...schema && {
1314
+ options: `-csearch_path=${schema}`
1315
+ }
1292
1316
  });
1293
1317
  this.logger.debug(`Schema keys passed to drizzle: [${Object.keys(this.options.drizzleSchema || {}).join(", ")}]`);
1294
1318
  this.logger.debug(`Relations keys passed to drizzle: [${Object.keys(this.options.drizzleRelations || {}).join(", ")}]`);
@@ -1299,35 +1323,12 @@ var PrimaryDatabaseService = class _PrimaryDatabaseService {
1299
1323
  });
1300
1324
  this.logger.debug(`Drizzle query keys after init: [${Object.keys(this.db.query || {}).join(", ")}]`);
1301
1325
  await this.pool.query("SELECT 1");
1302
- this.logger.log("Connected to primary database (tenant registry)");
1326
+ this.logger.log(`Connected to primary database (schema: ${schema ?? "public"})`);
1303
1327
  } catch (error) {
1304
1328
  this.logger.error("Failed to connect to primary database", error);
1305
1329
  throw new import_common38.InternalServerErrorException("Failed to initialize tenant registry");
1306
1330
  }
1307
1331
  }
1308
- // Builds the PostgreSQL connection URL from primary database config properties
1309
- buildPrimaryDbUrl() {
1310
- if (!this.options.primaryDb) {
1311
- throw new Error("Primary database configuration not provided");
1312
- }
1313
- const { host, port = 5432, username, password, database, schema = "public", sslMode = "require" } = this.options.primaryDb;
1314
- let url = `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
1315
- const params = new URLSearchParams();
1316
- if (schema) {
1317
- params.set("schema", schema);
1318
- }
1319
- params.set("sslmode", sslMode);
1320
- const queryString = params.toString();
1321
- if (queryString) {
1322
- url += `?${queryString}`;
1323
- }
1324
- this.logger.debug(`Primary DB connection URL: ${this.maskPassword(url)}`);
1325
- return url;
1326
- }
1327
- // Masks password in connection URL for safe logging
1328
- maskPassword(url) {
1329
- return url.replace(/:([^@]+)@/, ":****@");
1330
- }
1331
1332
  // Retrieves tenant configuration by ID or subdomain, with in-memory caching
1332
1333
  async getTenantInfo(tenantIdentifier) {
1333
1334
  const cached = this.tenantConfigCache.get(tenantIdentifier);
@@ -3110,7 +3111,7 @@ var HttpExceptionFilter = class _HttpExceptionFilter {
3110
3111
  let label;
3111
3112
  let detail = "Internal server error";
3112
3113
  let errors = [];
3113
- if (exception instanceof import_common47.HttpException) {
3114
+ if (this.isHttpException(exception)) {
3114
3115
  status = exception.getStatus();
3115
3116
  const exceptionResponse = exception.getResponse();
3116
3117
  if (typeof exceptionResponse === "object" && exceptionResponse !== null) {
@@ -3163,6 +3164,10 @@ var HttpExceptionFilter = class _HttpExceptionFilter {
3163
3164
  };
3164
3165
  response.header("Content-Type", "application/problem+json").status(status).send(problemDetails);
3165
3166
  }
3167
+ // Duck-type check for HttpException — avoids instanceof failing across pnpm package instances
3168
+ isHttpException(error) {
3169
+ return error instanceof Error && typeof error.getStatus === "function" && typeof error.getResponse === "function";
3170
+ }
3166
3171
  // Duck-type check for AxiosError without importing axios
3167
3172
  isAxiosError(error) {
3168
3173
  return error instanceof Error && error.isAxiosError === true;
@@ -3271,9 +3276,9 @@ var LoggerService = class _LoggerService {
3271
3276
  }) : new import_winston.transports.Console({
3272
3277
  level,
3273
3278
  format: import_winston.format.combine(...baseFormatters, import_winston.format.printf((info) => {
3274
- const { timestamp, level: level2, message, context, correlationId, trace } = info;
3279
+ const { timestamp: timestamp2, level: level2, message, context, correlationId, trace } = info;
3275
3280
  const parts = [
3276
- timestamp,
3281
+ timestamp2,
3277
3282
  level2.toUpperCase().padEnd(7),
3278
3283
  correlationId ? `[${correlationId.toString().slice(-6)}]` : "",
3279
3284
  context ? `[${context}]` : "",
@@ -4347,6 +4352,1064 @@ function normalizePhoneNumber(phone) {
4347
4352
  return phone.startsWith("+") ? phone : `+${phone}`;
4348
4353
  }
4349
4354
  __name(normalizePhoneNumber, "normalizePhoneNumber");
4355
+
4356
+ // src/data-table/data-table.module.ts
4357
+ var import_common65 = require("@nestjs/common");
4358
+ var import_config14 = require("@nestjs/config");
4359
+
4360
+ // src/data-table/data-table.constants.ts
4361
+ var DATA_TABLE_VIEWS_TABLE = Symbol("DATA_TABLE_VIEWS_TABLE");
4362
+
4363
+ // src/data-table/state/controllers/data-table-state.controller.ts
4364
+ var import_common60 = require("@nestjs/common");
4365
+ var import_swagger10 = require("@nestjs/swagger");
4366
+
4367
+ // src/data-table/state/docs/data-table-state.docs.ts
4368
+ var import_common58 = require("@nestjs/common");
4369
+ var import_swagger9 = require("@nestjs/swagger");
4370
+
4371
+ // src/data-table/state/dto/request/upsert-data-table-state.dto.ts
4372
+ var import_swagger8 = require("@nestjs/swagger");
4373
+ var import_class_validator3 = require("class-validator");
4374
+ function _ts_decorate27(decorators, target, key, desc2) {
4375
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4376
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4377
+ 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;
4378
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4379
+ }
4380
+ __name(_ts_decorate27, "_ts_decorate");
4381
+ function _ts_metadata17(k, v) {
4382
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4383
+ }
4384
+ __name(_ts_metadata17, "_ts_metadata");
4385
+ var UpsertDataTableStateDto = class {
4386
+ static {
4387
+ __name(this, "UpsertDataTableStateDto");
4388
+ }
4389
+ tableSlug;
4390
+ state;
4391
+ activeViewId;
4392
+ };
4393
+ _ts_decorate27([
4394
+ (0, import_swagger8.ApiProperty)({
4395
+ description: "Unique slug identifying the table",
4396
+ example: "cloud-providers"
4397
+ }),
4398
+ (0, import_class_validator3.IsString)(),
4399
+ (0, import_class_validator3.MaxLength)(100),
4400
+ _ts_metadata17("design:type", String)
4401
+ ], UpsertDataTableStateDto.prototype, "tableSlug", void 0);
4402
+ _ts_decorate27([
4403
+ (0, import_swagger8.ApiProperty)({
4404
+ description: "Full table view state including filters, sort, and column visibility"
4405
+ }),
4406
+ (0, import_class_validator3.IsObject)(),
4407
+ _ts_metadata17("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4408
+ ], UpsertDataTableStateDto.prototype, "state", void 0);
4409
+ _ts_decorate27([
4410
+ (0, import_swagger8.ApiPropertyOptional)(),
4411
+ (0, import_class_validator3.IsOptional)(),
4412
+ (0, import_class_validator3.IsUUID)(),
4413
+ _ts_metadata17("design:type", Object)
4414
+ ], UpsertDataTableStateDto.prototype, "activeViewId", void 0);
4415
+
4416
+ // src/data-table/state/docs/data-table-state.docs.ts
4417
+ function ApiUpsertDataTableState() {
4418
+ return (0, import_common58.applyDecorators)((0, import_swagger9.ApiOperation)({
4419
+ summary: "Save live table state",
4420
+ description: "Stores the current filter, sort, and column visibility state in Redis cache. Called on filter Apply and sort column click. State expires after TABLE_STATE_CACHE_TTL seconds."
4421
+ }), (0, import_swagger9.ApiBody)({
4422
+ type: UpsertDataTableStateDto
4423
+ }), (0, import_swagger9.ApiResponse)({
4424
+ status: 200,
4425
+ description: "Live state cached."
4426
+ }), (0, import_swagger9.ApiResponse)({
4427
+ status: 400,
4428
+ description: "Invalid request body."
4429
+ }), (0, import_swagger9.ApiResponse)({
4430
+ status: 401,
4431
+ description: "Unauthorized."
4432
+ }));
4433
+ }
4434
+ __name(ApiUpsertDataTableState, "ApiUpsertDataTableState");
4435
+
4436
+ // src/data-table/state/services/data-table-state.service.ts
4437
+ var import_common59 = require("@nestjs/common");
4438
+ var import_config12 = require("@nestjs/config");
4439
+ function _ts_decorate28(decorators, target, key, desc2) {
4440
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4441
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4442
+ 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;
4443
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4444
+ }
4445
+ __name(_ts_decorate28, "_ts_decorate");
4446
+ function _ts_metadata18(k, v) {
4447
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4448
+ }
4449
+ __name(_ts_metadata18, "_ts_metadata");
4450
+ var EMPTY_TABLE_STATE = {
4451
+ filters: [],
4452
+ sort: [],
4453
+ columnVisibility: {},
4454
+ columnOrder: [],
4455
+ columnSizing: {},
4456
+ columnPinning: {
4457
+ left: [],
4458
+ right: []
4459
+ },
4460
+ lockedColumnSizing: false,
4461
+ density: "normal",
4462
+ filterOrder: [],
4463
+ filterVisibility: {},
4464
+ pagination: {
4465
+ limit: 20,
4466
+ offset: 0
4467
+ }
4468
+ };
4469
+ var DataTableStateService = class _DataTableStateService {
4470
+ static {
4471
+ __name(this, "DataTableStateService");
4472
+ }
4473
+ cacheService;
4474
+ configService;
4475
+ logger = new import_common59.Logger(_DataTableStateService.name);
4476
+ constructor(cacheService, configService) {
4477
+ this.cacheService = cacheService;
4478
+ this.configService = configService;
4479
+ }
4480
+ // Returns configured TTL for live table state in seconds, defaulting to 3600 (1h)
4481
+ get stateTtl() {
4482
+ return this.configService.get("TABLE_STATE_CACHE_TTL") ?? 3600;
4483
+ }
4484
+ // Saves live table state and active view ID to Redis; DB is not written
4485
+ async upsertCurrentState(userId, dto) {
4486
+ const key = `dt:${userId}:${dto.tableSlug}`;
4487
+ await this.cacheService.set(key, {
4488
+ state: dto.state,
4489
+ activeViewId: dto.activeViewId ?? null
4490
+ }, this.stateTtl);
4491
+ this.logger.log(`Cached live state for user: ${userId}, table: ${dto.tableSlug}`);
4492
+ }
4493
+ // Returns live table state and active view ID from Redis; returns empty state on miss — no DB query
4494
+ async getCurrentState(userId, tableSlug) {
4495
+ const key = `dt:${userId}:${tableSlug}`;
4496
+ const cached = await this.cacheService.get(key);
4497
+ return cached ?? {
4498
+ state: EMPTY_TABLE_STATE,
4499
+ activeViewId: null
4500
+ };
4501
+ }
4502
+ };
4503
+ DataTableStateService = _ts_decorate28([
4504
+ (0, import_common59.Injectable)(),
4505
+ _ts_metadata18("design:type", Function),
4506
+ _ts_metadata18("design:paramtypes", [
4507
+ typeof CacheService === "undefined" ? Object : CacheService,
4508
+ typeof import_config12.ConfigService === "undefined" ? Object : import_config12.ConfigService
4509
+ ])
4510
+ ], DataTableStateService);
4511
+
4512
+ // src/data-table/state/controllers/data-table-state.controller.ts
4513
+ function _ts_decorate29(decorators, target, key, desc2) {
4514
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4515
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4516
+ 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;
4517
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4518
+ }
4519
+ __name(_ts_decorate29, "_ts_decorate");
4520
+ function _ts_metadata19(k, v) {
4521
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4522
+ }
4523
+ __name(_ts_metadata19, "_ts_metadata");
4524
+ function _ts_param8(paramIndex, decorator) {
4525
+ return function(target, key) {
4526
+ decorator(target, key, paramIndex);
4527
+ };
4528
+ }
4529
+ __name(_ts_param8, "_ts_param");
4530
+ var DataTableStateController = class _DataTableStateController {
4531
+ static {
4532
+ __name(this, "DataTableStateController");
4533
+ }
4534
+ dataTableStateService;
4535
+ logger = new import_common60.Logger(_DataTableStateController.name);
4536
+ constructor(dataTableStateService) {
4537
+ this.dataTableStateService = dataTableStateService;
4538
+ }
4539
+ // Saves live table state to Redis cache for the authenticated user's table
4540
+ upsertCurrentState(userId, dto) {
4541
+ this.logger.log(`POST /table-states - User: ${userId}, table: ${dto.tableSlug}`);
4542
+ return this.dataTableStateService.upsertCurrentState(userId, dto);
4543
+ }
4544
+ };
4545
+ _ts_decorate29([
4546
+ (0, import_common60.Post)(),
4547
+ (0, import_common60.HttpCode)(import_common60.HttpStatus.OK),
4548
+ ApiUpsertDataTableState(),
4549
+ _ts_param8(0, UserId()),
4550
+ _ts_param8(1, (0, import_common60.Body)()),
4551
+ _ts_metadata19("design:type", Function),
4552
+ _ts_metadata19("design:paramtypes", [
4553
+ String,
4554
+ typeof UpsertDataTableStateDto === "undefined" ? Object : UpsertDataTableStateDto
4555
+ ]),
4556
+ _ts_metadata19("design:returntype", typeof Promise === "undefined" ? Object : Promise)
4557
+ ], DataTableStateController.prototype, "upsertCurrentState", null);
4558
+ DataTableStateController = _ts_decorate29([
4559
+ (0, import_swagger10.ApiTags)("Table States"),
4560
+ (0, import_swagger10.ApiBearerAuth)(),
4561
+ (0, import_common60.Controller)("table-states"),
4562
+ _ts_metadata19("design:type", Function),
4563
+ _ts_metadata19("design:paramtypes", [
4564
+ typeof DataTableStateService === "undefined" ? Object : DataTableStateService
4565
+ ])
4566
+ ], DataTableStateController);
4567
+
4568
+ // src/data-table/views/controllers/data-table-views.controller.ts
4569
+ var import_common64 = require("@nestjs/common");
4570
+ var import_swagger17 = require("@nestjs/swagger");
4571
+
4572
+ // src/data-table/views/docs/data-table-views.docs.ts
4573
+ var import_common61 = require("@nestjs/common");
4574
+ var import_swagger16 = require("@nestjs/swagger");
4575
+
4576
+ // src/data-table/views/dto/entity/data-table-view.dto.ts
4577
+ var import_swagger11 = require("@nestjs/swagger");
4578
+ function _ts_decorate30(decorators, target, key, desc2) {
4579
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4580
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4581
+ 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;
4582
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4583
+ }
4584
+ __name(_ts_decorate30, "_ts_decorate");
4585
+ function _ts_metadata20(k, v) {
4586
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4587
+ }
4588
+ __name(_ts_metadata20, "_ts_metadata");
4589
+ var DataTableViewDto = class _DataTableViewDto {
4590
+ static {
4591
+ __name(this, "DataTableViewDto");
4592
+ }
4593
+ id;
4594
+ name;
4595
+ tableSlug;
4596
+ state;
4597
+ isShared;
4598
+ isOwn;
4599
+ createdAt;
4600
+ updatedAt;
4601
+ // Creates a response DTO from a DataTableView entity, computing isOwn by comparing userId
4602
+ static from(view, userId) {
4603
+ const dto = new _DataTableViewDto();
4604
+ dto.id = view.id;
4605
+ dto.name = view.name ?? null;
4606
+ dto.tableSlug = view.tableSlug;
4607
+ dto.state = view.state;
4608
+ dto.isShared = view.isShared;
4609
+ dto.isOwn = view.userId === userId;
4610
+ dto.createdAt = view.createdAt;
4611
+ dto.updatedAt = view.updatedAt ?? null;
4612
+ return dto;
4613
+ }
4614
+ };
4615
+ _ts_decorate30([
4616
+ (0, import_swagger11.ApiProperty)({
4617
+ description: "View unique identifier"
4618
+ }),
4619
+ _ts_metadata20("design:type", String)
4620
+ ], DataTableViewDto.prototype, "id", void 0);
4621
+ _ts_decorate30([
4622
+ (0, import_swagger11.ApiPropertyOptional)({
4623
+ description: "Display name of the view",
4624
+ nullable: true
4625
+ }),
4626
+ _ts_metadata20("design:type", Object)
4627
+ ], DataTableViewDto.prototype, "name", void 0);
4628
+ _ts_decorate30([
4629
+ (0, import_swagger11.ApiProperty)({
4630
+ description: "Slug of the table this view belongs to",
4631
+ example: "cloud-providers"
4632
+ }),
4633
+ _ts_metadata20("design:type", String)
4634
+ ], DataTableViewDto.prototype, "tableSlug", void 0);
4635
+ _ts_decorate30([
4636
+ (0, import_swagger11.ApiProperty)({
4637
+ description: "Stored filter, sort, and column visibility state"
4638
+ }),
4639
+ _ts_metadata20("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4640
+ ], DataTableViewDto.prototype, "state", void 0);
4641
+ _ts_decorate30([
4642
+ (0, import_swagger11.ApiProperty)({
4643
+ description: "Whether the view is visible to all users",
4644
+ example: false
4645
+ }),
4646
+ _ts_metadata20("design:type", Boolean)
4647
+ ], DataTableViewDto.prototype, "isShared", void 0);
4648
+ _ts_decorate30([
4649
+ (0, import_swagger11.ApiProperty)({
4650
+ description: "Whether the requesting user owns this view",
4651
+ example: true
4652
+ }),
4653
+ _ts_metadata20("design:type", Boolean)
4654
+ ], DataTableViewDto.prototype, "isOwn", void 0);
4655
+ _ts_decorate30([
4656
+ (0, import_swagger11.ApiProperty)({
4657
+ description: "Creation timestamp"
4658
+ }),
4659
+ _ts_metadata20("design:type", typeof Date === "undefined" ? Object : Date)
4660
+ ], DataTableViewDto.prototype, "createdAt", void 0);
4661
+ _ts_decorate30([
4662
+ (0, import_swagger11.ApiPropertyOptional)({
4663
+ description: "Last updated timestamp",
4664
+ nullable: true
4665
+ }),
4666
+ _ts_metadata20("design:type", Object)
4667
+ ], DataTableViewDto.prototype, "updatedAt", void 0);
4668
+
4669
+ // src/data-table/views/dto/request/create-data-table-view.dto.ts
4670
+ var import_swagger12 = require("@nestjs/swagger");
4671
+ var import_class_validator4 = require("class-validator");
4672
+ function _ts_decorate31(decorators, target, key, desc2) {
4673
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4674
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4675
+ 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;
4676
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4677
+ }
4678
+ __name(_ts_decorate31, "_ts_decorate");
4679
+ function _ts_metadata21(k, v) {
4680
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4681
+ }
4682
+ __name(_ts_metadata21, "_ts_metadata");
4683
+ var CreateDataTableViewDto = class {
4684
+ static {
4685
+ __name(this, "CreateDataTableViewDto");
4686
+ }
4687
+ name;
4688
+ tableSlug;
4689
+ state;
4690
+ isShared;
4691
+ };
4692
+ _ts_decorate31([
4693
+ (0, import_swagger12.ApiProperty)({
4694
+ description: "Display name for the saved view",
4695
+ example: "AWS Only"
4696
+ }),
4697
+ (0, import_class_validator4.IsString)(),
4698
+ (0, import_class_validator4.MaxLength)(100),
4699
+ _ts_metadata21("design:type", String)
4700
+ ], CreateDataTableViewDto.prototype, "name", void 0);
4701
+ _ts_decorate31([
4702
+ (0, import_swagger12.ApiProperty)({
4703
+ description: "Unique slug identifying the table",
4704
+ example: "cloud-providers"
4705
+ }),
4706
+ (0, import_class_validator4.IsString)(),
4707
+ (0, import_class_validator4.MaxLength)(100),
4708
+ _ts_metadata21("design:type", String)
4709
+ ], CreateDataTableViewDto.prototype, "tableSlug", void 0);
4710
+ _ts_decorate31([
4711
+ (0, import_swagger12.ApiProperty)({
4712
+ description: "Full table view state including filters, sort, and column visibility"
4713
+ }),
4714
+ (0, import_class_validator4.IsObject)(),
4715
+ _ts_metadata21("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4716
+ ], CreateDataTableViewDto.prototype, "state", void 0);
4717
+ _ts_decorate31([
4718
+ (0, import_swagger12.ApiPropertyOptional)({
4719
+ description: "Whether this view is visible to all users",
4720
+ example: false
4721
+ }),
4722
+ (0, import_class_validator4.IsBoolean)(),
4723
+ (0, import_class_validator4.IsOptional)(),
4724
+ _ts_metadata21("design:type", Boolean)
4725
+ ], CreateDataTableViewDto.prototype, "isShared", void 0);
4726
+
4727
+ // src/data-table/views/dto/request/rename-data-table-view.dto.ts
4728
+ var import_swagger13 = require("@nestjs/swagger");
4729
+ var import_class_validator5 = require("class-validator");
4730
+ function _ts_decorate32(decorators, target, key, desc2) {
4731
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4732
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4733
+ 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;
4734
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4735
+ }
4736
+ __name(_ts_decorate32, "_ts_decorate");
4737
+ function _ts_metadata22(k, v) {
4738
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4739
+ }
4740
+ __name(_ts_metadata22, "_ts_metadata");
4741
+ var RenameDataTableViewDto = class {
4742
+ static {
4743
+ __name(this, "RenameDataTableViewDto");
4744
+ }
4745
+ name;
4746
+ };
4747
+ _ts_decorate32([
4748
+ (0, import_swagger13.ApiProperty)({
4749
+ description: "New display name for the view",
4750
+ example: "AWS Only"
4751
+ }),
4752
+ (0, import_class_validator5.IsString)(),
4753
+ (0, import_class_validator5.MinLength)(1),
4754
+ (0, import_class_validator5.MaxLength)(100),
4755
+ _ts_metadata22("design:type", String)
4756
+ ], RenameDataTableViewDto.prototype, "name", void 0);
4757
+
4758
+ // src/data-table/views/dto/request/toggle-share-data-table-view.dto.ts
4759
+ var import_swagger14 = require("@nestjs/swagger");
4760
+ var import_class_validator6 = require("class-validator");
4761
+ function _ts_decorate33(decorators, target, key, desc2) {
4762
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4763
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4764
+ 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;
4765
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4766
+ }
4767
+ __name(_ts_decorate33, "_ts_decorate");
4768
+ function _ts_metadata23(k, v) {
4769
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4770
+ }
4771
+ __name(_ts_metadata23, "_ts_metadata");
4772
+ var ToggleShareDataTableViewDto = class {
4773
+ static {
4774
+ __name(this, "ToggleShareDataTableViewDto");
4775
+ }
4776
+ isShared;
4777
+ };
4778
+ _ts_decorate33([
4779
+ (0, import_swagger14.ApiProperty)({
4780
+ description: "Whether the view should be visible to all users",
4781
+ example: true
4782
+ }),
4783
+ (0, import_class_validator6.IsBoolean)(),
4784
+ _ts_metadata23("design:type", Boolean)
4785
+ ], ToggleShareDataTableViewDto.prototype, "isShared", void 0);
4786
+
4787
+ // src/data-table/views/dto/request/update-data-table-view.dto.ts
4788
+ var import_swagger15 = require("@nestjs/swagger");
4789
+ var import_class_validator7 = require("class-validator");
4790
+ function _ts_decorate34(decorators, target, key, desc2) {
4791
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4792
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4793
+ 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;
4794
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4795
+ }
4796
+ __name(_ts_decorate34, "_ts_decorate");
4797
+ function _ts_metadata24(k, v) {
4798
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4799
+ }
4800
+ __name(_ts_metadata24, "_ts_metadata");
4801
+ var UpdateDataTableViewDto = class {
4802
+ static {
4803
+ __name(this, "UpdateDataTableViewDto");
4804
+ }
4805
+ state;
4806
+ };
4807
+ _ts_decorate34([
4808
+ (0, import_swagger15.ApiProperty)({
4809
+ description: "Updated filter, sort, and column visibility state"
4810
+ }),
4811
+ (0, import_class_validator7.IsObject)(),
4812
+ _ts_metadata24("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4813
+ ], UpdateDataTableViewDto.prototype, "state", void 0);
4814
+
4815
+ // src/data-table/views/docs/data-table-views.docs.ts
4816
+ function ApiListDataTableViews() {
4817
+ return (0, import_common61.applyDecorators)((0, import_swagger16.ApiOperation)({
4818
+ summary: "List named table views",
4819
+ description: "Returns the authenticated user's own named views plus all shared views for the given table slug."
4820
+ }), (0, import_swagger16.ApiQuery)({
4821
+ name: "tableSlug",
4822
+ description: "Slug of the table to fetch views for",
4823
+ example: "cloud-providers",
4824
+ required: true
4825
+ }), (0, import_swagger16.ApiResponse)({
4826
+ status: 200,
4827
+ description: "Named views retrieved.",
4828
+ type: [
4829
+ DataTableViewDto
4830
+ ]
4831
+ }), (0, import_swagger16.ApiResponse)({
4832
+ status: 401,
4833
+ description: "Unauthorized."
4834
+ }));
4835
+ }
4836
+ __name(ApiListDataTableViews, "ApiListDataTableViews");
4837
+ function ApiCreateDataTableView() {
4838
+ return (0, import_common61.applyDecorators)((0, import_swagger16.ApiOperation)({
4839
+ summary: "Create named table view",
4840
+ description: "Saves the current table state as a named view snapshot. The name must be unique per user+table."
4841
+ }), (0, import_swagger16.ApiBody)({
4842
+ type: CreateDataTableViewDto
4843
+ }), (0, import_swagger16.ApiResponse)({
4844
+ status: 201,
4845
+ description: "Named view created.",
4846
+ type: DataTableViewDto
4847
+ }), (0, import_swagger16.ApiResponse)({
4848
+ status: 400,
4849
+ description: "Invalid request body."
4850
+ }), (0, import_swagger16.ApiResponse)({
4851
+ status: 401,
4852
+ description: "Unauthorized."
4853
+ }));
4854
+ }
4855
+ __name(ApiCreateDataTableView, "ApiCreateDataTableView");
4856
+ function ApiUpdateDataTableView() {
4857
+ return (0, import_common61.applyDecorators)((0, import_swagger16.ApiOperation)({
4858
+ summary: "Update named table view",
4859
+ description: "Updates the state of an existing named view. Only the owner can update."
4860
+ }), (0, import_swagger16.ApiParam)({
4861
+ name: "id",
4862
+ description: "UUID of the table view to update"
4863
+ }), (0, import_swagger16.ApiBody)({
4864
+ type: UpdateDataTableViewDto
4865
+ }), (0, import_swagger16.ApiResponse)({
4866
+ status: 200,
4867
+ description: "View updated.",
4868
+ type: DataTableViewDto
4869
+ }), (0, import_swagger16.ApiResponse)({
4870
+ status: 400,
4871
+ description: "Validation failed or not owned by caller."
4872
+ }), (0, import_swagger16.ApiResponse)({
4873
+ status: 401,
4874
+ description: "Unauthorized."
4875
+ }), (0, import_swagger16.ApiResponse)({
4876
+ status: 404,
4877
+ description: "View not found."
4878
+ }));
4879
+ }
4880
+ __name(ApiUpdateDataTableView, "ApiUpdateDataTableView");
4881
+ function ApiRenameDataTableView() {
4882
+ return (0, import_common61.applyDecorators)((0, import_swagger16.ApiOperation)({
4883
+ summary: "Rename a named table view",
4884
+ description: "Updates the display name of an existing view. The new name must be unique per user+table. Only the owner can rename."
4885
+ }), (0, import_swagger16.ApiParam)({
4886
+ name: "id",
4887
+ description: "UUID of the table view to rename"
4888
+ }), (0, import_swagger16.ApiBody)({
4889
+ type: RenameDataTableViewDto
4890
+ }), (0, import_swagger16.ApiResponse)({
4891
+ status: 200,
4892
+ description: "View renamed.",
4893
+ type: DataTableViewDto
4894
+ }), (0, import_swagger16.ApiResponse)({
4895
+ status: 400,
4896
+ description: "Not owned by caller."
4897
+ }), (0, import_swagger16.ApiResponse)({
4898
+ status: 401,
4899
+ description: "Unauthorized."
4900
+ }), (0, import_swagger16.ApiResponse)({
4901
+ status: 404,
4902
+ description: "View not found."
4903
+ }), (0, import_swagger16.ApiResponse)({
4904
+ status: 409,
4905
+ description: "A view with this name already exists."
4906
+ }));
4907
+ }
4908
+ __name(ApiRenameDataTableView, "ApiRenameDataTableView");
4909
+ function ApiToggleShareDataTableView() {
4910
+ return (0, import_common61.applyDecorators)((0, import_swagger16.ApiOperation)({
4911
+ summary: "Toggle view sharing",
4912
+ description: "Makes a view visible to all users (shared) or restricts it to the owner only (private). Only the owner can toggle sharing."
4913
+ }), (0, import_swagger16.ApiParam)({
4914
+ name: "id",
4915
+ description: "UUID of the table view"
4916
+ }), (0, import_swagger16.ApiBody)({
4917
+ type: ToggleShareDataTableViewDto
4918
+ }), (0, import_swagger16.ApiResponse)({
4919
+ status: 200,
4920
+ description: "Sharing status updated.",
4921
+ type: DataTableViewDto
4922
+ }), (0, import_swagger16.ApiResponse)({
4923
+ status: 400,
4924
+ description: "Not owned by caller."
4925
+ }), (0, import_swagger16.ApiResponse)({
4926
+ status: 401,
4927
+ description: "Unauthorized."
4928
+ }), (0, import_swagger16.ApiResponse)({
4929
+ status: 404,
4930
+ description: "View not found."
4931
+ }));
4932
+ }
4933
+ __name(ApiToggleShareDataTableView, "ApiToggleShareDataTableView");
4934
+ function ApiDeleteDataTableView() {
4935
+ return (0, import_common61.applyDecorators)((0, import_swagger16.ApiOperation)({
4936
+ summary: "Delete named table view",
4937
+ description: "Permanently deletes a named view. Only the owner can delete their own views."
4938
+ }), (0, import_swagger16.ApiParam)({
4939
+ name: "id",
4940
+ description: "UUID of the table view to delete"
4941
+ }), (0, import_swagger16.ApiResponse)({
4942
+ status: 200,
4943
+ description: "View deleted.",
4944
+ type: DataTableViewDto
4945
+ }), (0, import_swagger16.ApiResponse)({
4946
+ status: 400,
4947
+ description: "Not owned by caller."
4948
+ }), (0, import_swagger16.ApiResponse)({
4949
+ status: 401,
4950
+ description: "Unauthorized."
4951
+ }), (0, import_swagger16.ApiResponse)({
4952
+ status: 404,
4953
+ description: "View not found."
4954
+ }));
4955
+ }
4956
+ __name(ApiDeleteDataTableView, "ApiDeleteDataTableView");
4957
+
4958
+ // src/data-table/views/services/data-table-views.service.ts
4959
+ var import_node_crypto2 = require("crypto");
4960
+ var import_common63 = require("@nestjs/common");
4961
+ var import_config13 = require("@nestjs/config");
4962
+
4963
+ // src/data-table/views/repositories/data-table-views.repository.ts
4964
+ var import_common62 = require("@nestjs/common");
4965
+ var import_drizzle_orm5 = require("drizzle-orm");
4966
+ function _ts_decorate35(decorators, target, key, desc2) {
4967
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4968
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4969
+ 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;
4970
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4971
+ }
4972
+ __name(_ts_decorate35, "_ts_decorate");
4973
+ function _ts_metadata25(k, v) {
4974
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4975
+ }
4976
+ __name(_ts_metadata25, "_ts_metadata");
4977
+ function _ts_param9(paramIndex, decorator) {
4978
+ return function(target, key) {
4979
+ decorator(target, key, paramIndex);
4980
+ };
4981
+ }
4982
+ __name(_ts_param9, "_ts_param");
4983
+ var NAMED_VIEWS_LIMIT = 100;
4984
+ var DataTableViewsRepository = class extends PrimaryBaseRepository {
4985
+ static {
4986
+ __name(this, "DataTableViewsRepository");
4987
+ }
4988
+ constructor(database, table) {
4989
+ super(database, table);
4990
+ }
4991
+ // Returns personal (non-shared) named views owned by the user for a given table
4992
+ async findPersonalViewsBySlug(userId, tableSlug) {
4993
+ const t = this.table;
4994
+ return this.db.select().from(this.table).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.eq)(t.tableSlug, tableSlug), (0, import_drizzle_orm5.eq)(t.userId, userId), (0, import_drizzle_orm5.eq)(t.isShared, false))).orderBy(t.createdAt).limit(NAMED_VIEWS_LIMIT);
4995
+ }
4996
+ // Returns all shared named views for a given table — visible to all users
4997
+ async findSharedViewsBySlug(tableSlug) {
4998
+ const t = this.table;
4999
+ return this.db.select().from(this.table).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.eq)(t.tableSlug, tableSlug), (0, import_drizzle_orm5.eq)(t.isShared, true))).orderBy(t.createdAt).limit(NAMED_VIEWS_LIMIT);
5000
+ }
5001
+ };
5002
+ DataTableViewsRepository = _ts_decorate35([
5003
+ (0, import_common62.Injectable)(),
5004
+ _ts_param9(1, (0, import_common62.Inject)(DATA_TABLE_VIEWS_TABLE)),
5005
+ _ts_metadata25("design:type", Function),
5006
+ _ts_metadata25("design:paramtypes", [
5007
+ typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
5008
+ typeof PgTable === "undefined" ? Object : PgTable
5009
+ ])
5010
+ ], DataTableViewsRepository);
5011
+
5012
+ // src/data-table/views/services/data-table-views.service.ts
5013
+ function _ts_decorate36(decorators, target, key, desc2) {
5014
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
5015
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
5016
+ 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;
5017
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
5018
+ }
5019
+ __name(_ts_decorate36, "_ts_decorate");
5020
+ function _ts_metadata26(k, v) {
5021
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5022
+ }
5023
+ __name(_ts_metadata26, "_ts_metadata");
5024
+ function computeChecksum(value) {
5025
+ return (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(value)).digest("hex");
5026
+ }
5027
+ __name(computeChecksum, "computeChecksum");
5028
+ var DataTableViewsService = class _DataTableViewsService {
5029
+ static {
5030
+ __name(this, "DataTableViewsService");
5031
+ }
5032
+ dataTableViewsRepository;
5033
+ cacheService;
5034
+ configService;
5035
+ logger = new import_common63.Logger(_DataTableViewsService.name);
5036
+ constructor(dataTableViewsRepository, cacheService, configService) {
5037
+ this.dataTableViewsRepository = dataTableViewsRepository;
5038
+ this.cacheService = cacheService;
5039
+ this.configService = configService;
5040
+ }
5041
+ // Builds the Redis key for a user's personal (non-shared) views for a given table
5042
+ personalViewsKey(userId, tableSlug) {
5043
+ return `views:personal:${userId}:${tableSlug}`;
5044
+ }
5045
+ // Builds the Redis key for all shared views for a given table — same key for all users
5046
+ sharedViewsKey(tableSlug) {
5047
+ return `views:shared:${tableSlug}`;
5048
+ }
5049
+ // Returns configured TTL for named views in seconds, defaulting to 86400 (24h)
5050
+ get viewsTtl() {
5051
+ return this.configService.get("TABLE_VIEWS_CACHE_TTL") ?? 86400;
5052
+ }
5053
+ // Fetches personal views from cache; falls back to DB and warms cache on miss
5054
+ async getOrCachePersonalViews(userId, tableSlug) {
5055
+ const key = this.personalViewsKey(userId, tableSlug);
5056
+ const cached = await this.cacheService.get(key);
5057
+ if (cached) {
5058
+ this.logger.debug(`Cache hit for personal views: user=${userId}, table=${tableSlug}`);
5059
+ return cached;
5060
+ }
5061
+ const rows = await this.dataTableViewsRepository.findPersonalViewsBySlug(userId, tableSlug);
5062
+ await this.cacheService.set(key, rows, this.viewsTtl);
5063
+ return rows;
5064
+ }
5065
+ // Fetches shared views from cache; falls back to DB and warms cache on miss
5066
+ async getOrCacheSharedViews(tableSlug) {
5067
+ const key = this.sharedViewsKey(tableSlug);
5068
+ const cached = await this.cacheService.get(key);
5069
+ if (cached) {
5070
+ this.logger.debug(`Cache hit for shared views: table=${tableSlug}`);
5071
+ return cached;
5072
+ }
5073
+ const rows = await this.dataTableViewsRepository.findSharedViewsBySlug(tableSlug);
5074
+ await this.cacheService.set(key, rows, this.viewsTtl);
5075
+ return rows;
5076
+ }
5077
+ // Deletes personal and/or shared cache keys based on which pools the mutation affects
5078
+ async invalidateViewsCache(userId, tableSlug, affectsPersonal, affectsShared) {
5079
+ const toDelete = [];
5080
+ if (affectsPersonal) toDelete.push(this.personalViewsKey(userId, tableSlug));
5081
+ if (affectsShared) toDelete.push(this.sharedViewsKey(tableSlug));
5082
+ if (toDelete.length > 0) await this.cacheService.del(...toDelete);
5083
+ }
5084
+ // Returns personal + shared named views — each pool fetched from cache or DB in parallel
5085
+ async findViews(userId, tableSlug) {
5086
+ const [personalRows, sharedRows] = await Promise.all([
5087
+ this.getOrCachePersonalViews(userId, tableSlug),
5088
+ this.getOrCacheSharedViews(tableSlug)
5089
+ ]);
5090
+ return [
5091
+ ...personalRows,
5092
+ ...sharedRows
5093
+ ].map((row) => DataTableViewDto.from(row, userId));
5094
+ }
5095
+ // Creates a named snapshot and invalidates the relevant cache pool
5096
+ async createView(userId, dto) {
5097
+ const view = await this.dataTableViewsRepository.create({
5098
+ userId,
5099
+ tableSlug: dto.tableSlug,
5100
+ name: dto.name,
5101
+ state: dto.state,
5102
+ isShared: dto.isShared ?? false
5103
+ });
5104
+ this.logger.log(`Created view "${dto.name}" for user: ${userId}, table: ${dto.tableSlug}`);
5105
+ const isShared = dto.isShared ?? false;
5106
+ await this.invalidateViewsCache(userId, dto.tableSlug, !isShared, isShared);
5107
+ return DataTableViewDto.from(view, userId);
5108
+ }
5109
+ // Updates the state of a named view — skips DB write if state is unchanged
5110
+ async updateView(userId, id, dto) {
5111
+ const view = await this.dataTableViewsRepository.findById(id);
5112
+ if (!view) throw new NotFoundException("Table view not found.");
5113
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to update this view.");
5114
+ if (computeChecksum(dto.state) === computeChecksum(view.state)) {
5115
+ this.logger.log(`State unchanged for view ${id} \u2014 skipping DB write`);
5116
+ return DataTableViewDto.from(view, userId);
5117
+ }
5118
+ const updated = await this.dataTableViewsRepository.update(id, {
5119
+ state: dto.state
5120
+ });
5121
+ this.logger.log(`Updated state for view ${id}, user: ${userId}`);
5122
+ await this.invalidateViewsCache(userId, view.tableSlug, !view.isShared, view.isShared);
5123
+ return DataTableViewDto.from(updated, userId);
5124
+ }
5125
+ // Toggles the sharing status of a named view — updates both personal and shared cache
5126
+ async toggleShareView(userId, id, isShared) {
5127
+ const view = await this.dataTableViewsRepository.findById(id);
5128
+ if (!view) throw new NotFoundException("Table view not found.");
5129
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to share this view.");
5130
+ const updated = await this.dataTableViewsRepository.update(id, {
5131
+ isShared
5132
+ });
5133
+ this.logger.log(`Set isShared=${isShared} for view ${id}, user: ${userId}`);
5134
+ await this.invalidateViewsCache(userId, view.tableSlug, true, true);
5135
+ return DataTableViewDto.from(updated, userId);
5136
+ }
5137
+ // Renames a named view — enforces unique name per user+table, invalidates personal cache
5138
+ async renameView(userId, id, name) {
5139
+ const view = await this.dataTableViewsRepository.findById(id);
5140
+ if (!view) throw new NotFoundException("Table view not found.");
5141
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to rename this view.");
5142
+ const existing = await this.dataTableViewsRepository.findOne({
5143
+ userId,
5144
+ tableSlug: view.tableSlug,
5145
+ name,
5146
+ isShared: false
5147
+ });
5148
+ if (existing && existing.id !== id) {
5149
+ throw new ConflictException({
5150
+ label: "Name Already Taken",
5151
+ detail: "A view with this name already exists for this table.",
5152
+ errors: [
5153
+ {
5154
+ field: "name",
5155
+ message: "Name already taken"
5156
+ }
5157
+ ]
5158
+ });
5159
+ }
5160
+ const updated = await this.dataTableViewsRepository.update(id, {
5161
+ name
5162
+ });
5163
+ this.logger.log(`Renamed view ${id} to "${name}" for user: ${userId}`);
5164
+ await this.invalidateViewsCache(userId, view.tableSlug, !view.isShared, view.isShared);
5165
+ return DataTableViewDto.from(updated, userId);
5166
+ }
5167
+ // Deletes a named view and invalidates the relevant cache pool
5168
+ async deleteView(userId, id) {
5169
+ const view = await this.dataTableViewsRepository.findById(id);
5170
+ if (!view) throw new NotFoundException("Table view not found.");
5171
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to delete this view.");
5172
+ await this.dataTableViewsRepository.delete(id);
5173
+ this.logger.log(`Deleted view ${id} for user: ${userId}`);
5174
+ await this.invalidateViewsCache(userId, view.tableSlug, !view.isShared, view.isShared);
5175
+ return DataTableViewDto.from(view, userId);
5176
+ }
5177
+ };
5178
+ DataTableViewsService = _ts_decorate36([
5179
+ (0, import_common63.Injectable)(),
5180
+ _ts_metadata26("design:type", Function),
5181
+ _ts_metadata26("design:paramtypes", [
5182
+ typeof DataTableViewsRepository === "undefined" ? Object : DataTableViewsRepository,
5183
+ typeof CacheService === "undefined" ? Object : CacheService,
5184
+ typeof import_config13.ConfigService === "undefined" ? Object : import_config13.ConfigService
5185
+ ])
5186
+ ], DataTableViewsService);
5187
+
5188
+ // src/data-table/views/controllers/data-table-views.controller.ts
5189
+ function _ts_decorate37(decorators, target, key, desc2) {
5190
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
5191
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
5192
+ 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;
5193
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
5194
+ }
5195
+ __name(_ts_decorate37, "_ts_decorate");
5196
+ function _ts_metadata27(k, v) {
5197
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5198
+ }
5199
+ __name(_ts_metadata27, "_ts_metadata");
5200
+ function _ts_param10(paramIndex, decorator) {
5201
+ return function(target, key) {
5202
+ decorator(target, key, paramIndex);
5203
+ };
5204
+ }
5205
+ __name(_ts_param10, "_ts_param");
5206
+ var DataTableViewsController = class _DataTableViewsController {
5207
+ static {
5208
+ __name(this, "DataTableViewsController");
5209
+ }
5210
+ dataTableViewsService;
5211
+ logger = new import_common64.Logger(_DataTableViewsController.name);
5212
+ constructor(dataTableViewsService) {
5213
+ this.dataTableViewsService = dataTableViewsService;
5214
+ }
5215
+ // Returns all named views for the given table — own plus shared
5216
+ findViews(userId, tableSlug) {
5217
+ this.logger.log(`GET /table-views?tableSlug=${tableSlug} - User: ${userId}`);
5218
+ return this.dataTableViewsService.findViews(userId, tableSlug);
5219
+ }
5220
+ // Creates a named snapshot of the current table state
5221
+ createView(userId, dto) {
5222
+ this.logger.log(`POST /table-views - User: ${userId}, table: ${dto.tableSlug}`);
5223
+ return this.dataTableViewsService.createView(userId, dto);
5224
+ }
5225
+ // Updates state of an existing named view
5226
+ updateView(userId, id, dto) {
5227
+ this.logger.log(`PATCH /table-views/${id} - User: ${userId}`);
5228
+ return this.dataTableViewsService.updateView(userId, id, dto);
5229
+ }
5230
+ // Renames an existing named view — enforces unique name per user+table
5231
+ renameView(userId, id, dto) {
5232
+ this.logger.log(`PATCH /table-views/${id}/rename - User: ${userId}`);
5233
+ return this.dataTableViewsService.renameView(userId, id, dto.name);
5234
+ }
5235
+ // Toggles sharing visibility of a named view
5236
+ toggleShareView(userId, id, dto) {
5237
+ this.logger.log(`PATCH /table-views/${id}/share - User: ${userId}`);
5238
+ return this.dataTableViewsService.toggleShareView(userId, id, dto.isShared);
5239
+ }
5240
+ // Deletes a named view owned by the authenticated user
5241
+ deleteView(userId, id) {
5242
+ this.logger.log(`DELETE /table-views/${id} - User: ${userId}`);
5243
+ return this.dataTableViewsService.deleteView(userId, id);
5244
+ }
5245
+ };
5246
+ _ts_decorate37([
5247
+ (0, import_common64.Get)(),
5248
+ ApiListDataTableViews(),
5249
+ _ts_param10(0, UserId()),
5250
+ _ts_param10(1, (0, import_common64.Query)("tableSlug")),
5251
+ _ts_metadata27("design:type", Function),
5252
+ _ts_metadata27("design:paramtypes", [
5253
+ String,
5254
+ String
5255
+ ]),
5256
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5257
+ ], DataTableViewsController.prototype, "findViews", null);
5258
+ _ts_decorate37([
5259
+ (0, import_common64.Post)(),
5260
+ (0, import_common64.HttpCode)(import_common64.HttpStatus.CREATED),
5261
+ ApiCreateDataTableView(),
5262
+ _ts_param10(0, UserId()),
5263
+ _ts_param10(1, (0, import_common64.Body)()),
5264
+ _ts_metadata27("design:type", Function),
5265
+ _ts_metadata27("design:paramtypes", [
5266
+ String,
5267
+ typeof CreateDataTableViewDto === "undefined" ? Object : CreateDataTableViewDto
5268
+ ]),
5269
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5270
+ ], DataTableViewsController.prototype, "createView", null);
5271
+ _ts_decorate37([
5272
+ (0, import_common64.Patch)(":id"),
5273
+ ApiUpdateDataTableView(),
5274
+ _ts_param10(0, UserId()),
5275
+ _ts_param10(1, (0, import_common64.Param)("id")),
5276
+ _ts_param10(2, (0, import_common64.Body)()),
5277
+ _ts_metadata27("design:type", Function),
5278
+ _ts_metadata27("design:paramtypes", [
5279
+ String,
5280
+ String,
5281
+ typeof UpdateDataTableViewDto === "undefined" ? Object : UpdateDataTableViewDto
5282
+ ]),
5283
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5284
+ ], DataTableViewsController.prototype, "updateView", null);
5285
+ _ts_decorate37([
5286
+ (0, import_common64.Patch)(":id/rename"),
5287
+ ApiRenameDataTableView(),
5288
+ _ts_param10(0, UserId()),
5289
+ _ts_param10(1, (0, import_common64.Param)("id")),
5290
+ _ts_param10(2, (0, import_common64.Body)()),
5291
+ _ts_metadata27("design:type", Function),
5292
+ _ts_metadata27("design:paramtypes", [
5293
+ String,
5294
+ String,
5295
+ typeof RenameDataTableViewDto === "undefined" ? Object : RenameDataTableViewDto
5296
+ ]),
5297
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5298
+ ], DataTableViewsController.prototype, "renameView", null);
5299
+ _ts_decorate37([
5300
+ (0, import_common64.Patch)(":id/share"),
5301
+ ApiToggleShareDataTableView(),
5302
+ _ts_param10(0, UserId()),
5303
+ _ts_param10(1, (0, import_common64.Param)("id")),
5304
+ _ts_param10(2, (0, import_common64.Body)()),
5305
+ _ts_metadata27("design:type", Function),
5306
+ _ts_metadata27("design:paramtypes", [
5307
+ String,
5308
+ String,
5309
+ typeof ToggleShareDataTableViewDto === "undefined" ? Object : ToggleShareDataTableViewDto
5310
+ ]),
5311
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5312
+ ], DataTableViewsController.prototype, "toggleShareView", null);
5313
+ _ts_decorate37([
5314
+ (0, import_common64.Delete)(":id"),
5315
+ ApiDeleteDataTableView(),
5316
+ _ts_param10(0, UserId()),
5317
+ _ts_param10(1, (0, import_common64.Param)("id")),
5318
+ _ts_metadata27("design:type", Function),
5319
+ _ts_metadata27("design:paramtypes", [
5320
+ String,
5321
+ String
5322
+ ]),
5323
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5324
+ ], DataTableViewsController.prototype, "deleteView", null);
5325
+ DataTableViewsController = _ts_decorate37([
5326
+ (0, import_swagger17.ApiTags)("Table Views"),
5327
+ (0, import_swagger17.ApiBearerAuth)(),
5328
+ (0, import_common64.Controller)("table-views"),
5329
+ _ts_metadata27("design:type", Function),
5330
+ _ts_metadata27("design:paramtypes", [
5331
+ typeof DataTableViewsService === "undefined" ? Object : DataTableViewsService
5332
+ ])
5333
+ ], DataTableViewsController);
5334
+
5335
+ // src/data-table/data-table.module.ts
5336
+ function _ts_decorate38(decorators, target, key, desc2) {
5337
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
5338
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
5339
+ 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;
5340
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
5341
+ }
5342
+ __name(_ts_decorate38, "_ts_decorate");
5343
+ var DataTableModule = class _DataTableModule {
5344
+ static {
5345
+ __name(this, "DataTableModule");
5346
+ }
5347
+ static forRoot(options) {
5348
+ return {
5349
+ global: true,
5350
+ module: _DataTableModule,
5351
+ imports: [
5352
+ import_config14.ConfigModule,
5353
+ CacheModule
5354
+ ],
5355
+ controllers: [
5356
+ DataTableStateController,
5357
+ DataTableViewsController
5358
+ ],
5359
+ providers: [
5360
+ {
5361
+ provide: DATA_TABLE_VIEWS_TABLE,
5362
+ useValue: options.tableViews
5363
+ },
5364
+ DataTableViewsService,
5365
+ DataTableViewsRepository,
5366
+ DataTableStateService
5367
+ ],
5368
+ exports: [
5369
+ DataTableViewsService,
5370
+ DataTableStateService
5371
+ ]
5372
+ };
5373
+ }
5374
+ };
5375
+ DataTableModule = _ts_decorate38([
5376
+ (0, import_common65.Module)({})
5377
+ ], DataTableModule);
5378
+
5379
+ // src/drizzle-pg-core.ts
5380
+ var drizzle_pg_core_exports = {};
5381
+ __reExport(drizzle_pg_core_exports, require("drizzle-orm/pg-core"));
5382
+
5383
+ // src/data-table/schema/data-table-views.table.ts
5384
+ function dataTableViewsColumns() {
5385
+ return {
5386
+ id: (0, drizzle_pg_core_exports.uuid)("id").primaryKey().defaultRandom(),
5387
+ userId: (0, drizzle_pg_core_exports.uuid)("user_id").notNull(),
5388
+ tableSlug: (0, drizzle_pg_core_exports.varchar)("table_slug", {
5389
+ length: 100
5390
+ }).notNull(),
5391
+ name: (0, drizzle_pg_core_exports.varchar)("name", {
5392
+ length: 100
5393
+ }).notNull(),
5394
+ state: (0, drizzle_pg_core_exports.jsonb)("state").notNull().$type(),
5395
+ isShared: (0, drizzle_pg_core_exports.boolean)("is_shared").notNull().default(false),
5396
+ createdAt: (0, drizzle_pg_core_exports.timestamp)("created_at", {
5397
+ withTimezone: true
5398
+ }).notNull().defaultNow(),
5399
+ updatedAt: (0, drizzle_pg_core_exports.timestamp)("updated_at", {
5400
+ withTimezone: true
5401
+ }).$onUpdate(() => /* @__PURE__ */ new Date())
5402
+ };
5403
+ }
5404
+ __name(dataTableViewsColumns, "dataTableViewsColumns");
5405
+ function dataTableViewsIndexes(table) {
5406
+ return [
5407
+ (0, drizzle_pg_core_exports.index)("table_views_user_table_idx").on(table.userId, table.tableSlug),
5408
+ (0, drizzle_pg_core_exports.index)("table_views_shared_slug_idx").on(table.tableSlug, table.isShared),
5409
+ (0, drizzle_pg_core_exports.uniqueIndex)("table_views_user_table_name_shared_unique").on(table.userId, table.tableSlug, table.name, table.isShared)
5410
+ ];
5411
+ }
5412
+ __name(dataTableViewsIndexes, "dataTableViewsIndexes");
4350
5413
  // Annotate the CommonJS export names for ESM import in node:
4351
5414
  0 && (module.exports = {
4352
5415
  AccessToken,
@@ -4359,7 +5422,13 @@ __name(normalizePhoneNumber, "normalizePhoneNumber");
4359
5422
  ConflictException,
4360
5423
  CookieDomain,
4361
5424
  CorrelationIdMiddleware,
5425
+ CreateDataTableViewDto,
5426
+ DATA_TABLE_VIEWS_TABLE,
4362
5427
  DEFAULT_CORRELATION_HEADER,
5428
+ DataTableModule,
5429
+ DataTableStateService,
5430
+ DataTableViewDto,
5431
+ DataTableViewsService,
4363
5432
  DatabaseModule,
4364
5433
  EmailModule,
4365
5434
  EmailService,
@@ -4387,6 +5456,7 @@ __name(normalizePhoneNumber, "normalizePhoneNumber");
4387
5456
  RedisCacheProvider,
4388
5457
  RefreshCookieOptions,
4389
5458
  RefreshTokenCookie,
5459
+ RenameDataTableViewDto,
4390
5460
  RequestTimeoutException,
4391
5461
  Reset,
4392
5462
  RootModule,
@@ -4401,17 +5471,22 @@ __name(normalizePhoneNumber, "normalizePhoneNumber");
4401
5471
  TenantBaseRepository,
4402
5472
  TenantContextService,
4403
5473
  TenantDatabaseService,
5474
+ ToggleShareDataTableViewDto,
4404
5475
  TokenType,
4405
5476
  TooManyRequestsException,
4406
5477
  UnauthorizedException,
4407
5478
  UnprocessableEntityException,
4408
5479
  UnsupportedMediaTypeException,
5480
+ UpdateDataTableViewDto,
5481
+ UpsertDataTableStateDto,
4409
5482
  UserId,
4410
5483
  ValidationException,
4411
5484
  VrittiAuthGuard,
4412
5485
  addCorrelationIdToResponse,
4413
5486
  configureApiSdk,
4414
5487
  correlationStorage,
5488
+ dataTableViewsColumns,
5489
+ dataTableViewsIndexes,
4415
5490
  defineConfig,
4416
5491
  extractCountryFromPhone,
4417
5492
  generateCorrelationId,