@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.js CHANGED
@@ -1,5 +1,17 @@
1
1
  var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
2
5
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
+ var __copyProps = (to, from, except, desc2) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
3
15
 
4
16
  // src/auth/auth-config.module.ts
5
17
  import { Global as Global2, Module as Module2 } from "@nestjs/common";
@@ -1171,10 +1183,21 @@ var PrimaryDatabaseService = class _PrimaryDatabaseService {
1171
1183
  // Initializes connection to primary database using Drizzle
1172
1184
  async initializeDrizzleClient() {
1173
1185
  try {
1174
- const databaseUrl = this.buildPrimaryDbUrl();
1186
+ const { host, port = 5432, username, password, database, schema, sslMode = "require" } = this.options.primaryDb;
1175
1187
  this.pool = new Pool({
1176
- connectionString: databaseUrl,
1177
- max: this.options.maxConnections || 10
1188
+ host,
1189
+ port,
1190
+ user: username,
1191
+ password,
1192
+ database,
1193
+ max: this.options.maxConnections || 10,
1194
+ ssl: sslMode === "disable" ? false : {
1195
+ rejectUnauthorized: sslMode !== "no-verify"
1196
+ },
1197
+ // Pass schema as a PostgreSQL startup option — recognized by node-postgres, unlike the ?schema= URL param
1198
+ ...schema && {
1199
+ options: `-csearch_path=${schema}`
1200
+ }
1178
1201
  });
1179
1202
  this.logger.debug(`Schema keys passed to drizzle: [${Object.keys(this.options.drizzleSchema || {}).join(", ")}]`);
1180
1203
  this.logger.debug(`Relations keys passed to drizzle: [${Object.keys(this.options.drizzleRelations || {}).join(", ")}]`);
@@ -1185,35 +1208,12 @@ var PrimaryDatabaseService = class _PrimaryDatabaseService {
1185
1208
  });
1186
1209
  this.logger.debug(`Drizzle query keys after init: [${Object.keys(this.db.query || {}).join(", ")}]`);
1187
1210
  await this.pool.query("SELECT 1");
1188
- this.logger.log("Connected to primary database (tenant registry)");
1211
+ this.logger.log(`Connected to primary database (schema: ${schema ?? "public"})`);
1189
1212
  } catch (error) {
1190
1213
  this.logger.error("Failed to connect to primary database", error);
1191
1214
  throw new InternalServerErrorException2("Failed to initialize tenant registry");
1192
1215
  }
1193
1216
  }
1194
- // Builds the PostgreSQL connection URL from primary database config properties
1195
- buildPrimaryDbUrl() {
1196
- if (!this.options.primaryDb) {
1197
- throw new Error("Primary database configuration not provided");
1198
- }
1199
- const { host, port = 5432, username, password, database, schema = "public", sslMode = "require" } = this.options.primaryDb;
1200
- let url = `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
1201
- const params = new URLSearchParams();
1202
- if (schema) {
1203
- params.set("schema", schema);
1204
- }
1205
- params.set("sslmode", sslMode);
1206
- const queryString = params.toString();
1207
- if (queryString) {
1208
- url += `?${queryString}`;
1209
- }
1210
- this.logger.debug(`Primary DB connection URL: ${this.maskPassword(url)}`);
1211
- return url;
1212
- }
1213
- // Masks password in connection URL for safe logging
1214
- maskPassword(url) {
1215
- return url.replace(/:([^@]+)@/, ":****@");
1216
- }
1217
1217
  // Retrieves tenant configuration by ID or subdomain, with in-memory caching
1218
1218
  async getTenantInfo(tenantIdentifier) {
1219
1219
  const cached = this.tenantConfigCache.get(tenantIdentifier);
@@ -2966,7 +2966,7 @@ EmailModule = _ts_decorate17([
2966
2966
  ], EmailModule);
2967
2967
 
2968
2968
  // src/filters/http-exception.filter.ts
2969
- import { Catch, HttpException as HttpException2, HttpStatus as HttpStatus19, Logger as Logger11 } from "@nestjs/common";
2969
+ import { Catch, HttpStatus as HttpStatus19, Logger as Logger11 } from "@nestjs/common";
2970
2970
  function _ts_decorate18(decorators, target, key, desc2) {
2971
2971
  var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
2972
2972
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
@@ -2996,7 +2996,7 @@ var HttpExceptionFilter = class _HttpExceptionFilter {
2996
2996
  let label;
2997
2997
  let detail = "Internal server error";
2998
2998
  let errors = [];
2999
- if (exception instanceof HttpException2) {
2999
+ if (this.isHttpException(exception)) {
3000
3000
  status = exception.getStatus();
3001
3001
  const exceptionResponse = exception.getResponse();
3002
3002
  if (typeof exceptionResponse === "object" && exceptionResponse !== null) {
@@ -3049,6 +3049,10 @@ var HttpExceptionFilter = class _HttpExceptionFilter {
3049
3049
  };
3050
3050
  response.header("Content-Type", "application/problem+json").status(status).send(problemDetails);
3051
3051
  }
3052
+ // Duck-type check for HttpException — avoids instanceof failing across pnpm package instances
3053
+ isHttpException(error) {
3054
+ return error instanceof Error && typeof error.getStatus === "function" && typeof error.getResponse === "function";
3055
+ }
3052
3056
  // Duck-type check for AxiosError without importing axios
3053
3057
  isAxiosError(error) {
3054
3058
  return error instanceof Error && error.isAxiosError === true;
@@ -3157,9 +3161,9 @@ var LoggerService = class _LoggerService {
3157
3161
  }) : new transports.Console({
3158
3162
  level,
3159
3163
  format: format.combine(...baseFormatters, format.printf((info) => {
3160
- const { timestamp, level: level2, message, context, correlationId, trace } = info;
3164
+ const { timestamp: timestamp2, level: level2, message, context, correlationId, trace } = info;
3161
3165
  const parts = [
3162
- timestamp,
3166
+ timestamp2,
3163
3167
  level2.toUpperCase().padEnd(7),
3164
3168
  correlationId ? `[${correlationId.toString().slice(-6)}]` : "",
3165
3169
  context ? `[${context}]` : "",
@@ -4233,6 +4237,1065 @@ function normalizePhoneNumber(phone) {
4233
4237
  return phone.startsWith("+") ? phone : `+${phone}`;
4234
4238
  }
4235
4239
  __name(normalizePhoneNumber, "normalizePhoneNumber");
4240
+
4241
+ // src/data-table/data-table.module.ts
4242
+ import { Module as Module8 } from "@nestjs/common";
4243
+ import { ConfigModule as ConfigModule4 } from "@nestjs/config";
4244
+
4245
+ // src/data-table/data-table.constants.ts
4246
+ var DATA_TABLE_VIEWS_TABLE = Symbol("DATA_TABLE_VIEWS_TABLE");
4247
+
4248
+ // src/data-table/state/controllers/data-table-state.controller.ts
4249
+ import { Body, Controller as Controller3, HttpCode as HttpCode2, HttpStatus as HttpStatus21, Logger as Logger14, Post } from "@nestjs/common";
4250
+ import { ApiBearerAuth, ApiTags as ApiTags3 } from "@nestjs/swagger";
4251
+
4252
+ // src/data-table/state/docs/data-table-state.docs.ts
4253
+ import { applyDecorators as applyDecorators3 } from "@nestjs/common";
4254
+ import { ApiBody, ApiOperation as ApiOperation3, ApiResponse as ApiResponse3 } from "@nestjs/swagger";
4255
+
4256
+ // src/data-table/state/dto/request/upsert-data-table-state.dto.ts
4257
+ import { ApiProperty as ApiProperty3, ApiPropertyOptional as ApiPropertyOptional3 } from "@nestjs/swagger";
4258
+ import { IsObject, IsOptional as IsOptional2, IsString as IsString3, IsUUID, MaxLength } from "class-validator";
4259
+ function _ts_decorate27(decorators, target, key, desc2) {
4260
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4261
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4262
+ 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;
4263
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4264
+ }
4265
+ __name(_ts_decorate27, "_ts_decorate");
4266
+ function _ts_metadata17(k, v) {
4267
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4268
+ }
4269
+ __name(_ts_metadata17, "_ts_metadata");
4270
+ var UpsertDataTableStateDto = class {
4271
+ static {
4272
+ __name(this, "UpsertDataTableStateDto");
4273
+ }
4274
+ tableSlug;
4275
+ state;
4276
+ activeViewId;
4277
+ };
4278
+ _ts_decorate27([
4279
+ ApiProperty3({
4280
+ description: "Unique slug identifying the table",
4281
+ example: "cloud-providers"
4282
+ }),
4283
+ IsString3(),
4284
+ MaxLength(100),
4285
+ _ts_metadata17("design:type", String)
4286
+ ], UpsertDataTableStateDto.prototype, "tableSlug", void 0);
4287
+ _ts_decorate27([
4288
+ ApiProperty3({
4289
+ description: "Full table view state including filters, sort, and column visibility"
4290
+ }),
4291
+ IsObject(),
4292
+ _ts_metadata17("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4293
+ ], UpsertDataTableStateDto.prototype, "state", void 0);
4294
+ _ts_decorate27([
4295
+ ApiPropertyOptional3(),
4296
+ IsOptional2(),
4297
+ IsUUID(),
4298
+ _ts_metadata17("design:type", Object)
4299
+ ], UpsertDataTableStateDto.prototype, "activeViewId", void 0);
4300
+
4301
+ // src/data-table/state/docs/data-table-state.docs.ts
4302
+ function ApiUpsertDataTableState() {
4303
+ return applyDecorators3(ApiOperation3({
4304
+ summary: "Save live table state",
4305
+ 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."
4306
+ }), ApiBody({
4307
+ type: UpsertDataTableStateDto
4308
+ }), ApiResponse3({
4309
+ status: 200,
4310
+ description: "Live state cached."
4311
+ }), ApiResponse3({
4312
+ status: 400,
4313
+ description: "Invalid request body."
4314
+ }), ApiResponse3({
4315
+ status: 401,
4316
+ description: "Unauthorized."
4317
+ }));
4318
+ }
4319
+ __name(ApiUpsertDataTableState, "ApiUpsertDataTableState");
4320
+
4321
+ // src/data-table/state/services/data-table-state.service.ts
4322
+ import { Injectable as Injectable14, Logger as Logger13 } from "@nestjs/common";
4323
+ import { ConfigService as ConfigService6 } from "@nestjs/config";
4324
+ function _ts_decorate28(decorators, target, key, desc2) {
4325
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4326
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4327
+ 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;
4328
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4329
+ }
4330
+ __name(_ts_decorate28, "_ts_decorate");
4331
+ function _ts_metadata18(k, v) {
4332
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4333
+ }
4334
+ __name(_ts_metadata18, "_ts_metadata");
4335
+ var EMPTY_TABLE_STATE = {
4336
+ filters: [],
4337
+ sort: [],
4338
+ columnVisibility: {},
4339
+ columnOrder: [],
4340
+ columnSizing: {},
4341
+ columnPinning: {
4342
+ left: [],
4343
+ right: []
4344
+ },
4345
+ lockedColumnSizing: false,
4346
+ density: "normal",
4347
+ filterOrder: [],
4348
+ filterVisibility: {},
4349
+ pagination: {
4350
+ limit: 20,
4351
+ offset: 0
4352
+ }
4353
+ };
4354
+ var DataTableStateService = class _DataTableStateService {
4355
+ static {
4356
+ __name(this, "DataTableStateService");
4357
+ }
4358
+ cacheService;
4359
+ configService;
4360
+ logger = new Logger13(_DataTableStateService.name);
4361
+ constructor(cacheService, configService) {
4362
+ this.cacheService = cacheService;
4363
+ this.configService = configService;
4364
+ }
4365
+ // Returns configured TTL for live table state in seconds, defaulting to 3600 (1h)
4366
+ get stateTtl() {
4367
+ return this.configService.get("TABLE_STATE_CACHE_TTL") ?? 3600;
4368
+ }
4369
+ // Saves live table state and active view ID to Redis; DB is not written
4370
+ async upsertCurrentState(userId, dto) {
4371
+ const key = `dt:${userId}:${dto.tableSlug}`;
4372
+ await this.cacheService.set(key, {
4373
+ state: dto.state,
4374
+ activeViewId: dto.activeViewId ?? null
4375
+ }, this.stateTtl);
4376
+ this.logger.log(`Cached live state for user: ${userId}, table: ${dto.tableSlug}`);
4377
+ }
4378
+ // Returns live table state and active view ID from Redis; returns empty state on miss — no DB query
4379
+ async getCurrentState(userId, tableSlug) {
4380
+ const key = `dt:${userId}:${tableSlug}`;
4381
+ const cached = await this.cacheService.get(key);
4382
+ return cached ?? {
4383
+ state: EMPTY_TABLE_STATE,
4384
+ activeViewId: null
4385
+ };
4386
+ }
4387
+ };
4388
+ DataTableStateService = _ts_decorate28([
4389
+ Injectable14(),
4390
+ _ts_metadata18("design:type", Function),
4391
+ _ts_metadata18("design:paramtypes", [
4392
+ typeof CacheService === "undefined" ? Object : CacheService,
4393
+ typeof ConfigService6 === "undefined" ? Object : ConfigService6
4394
+ ])
4395
+ ], DataTableStateService);
4396
+
4397
+ // src/data-table/state/controllers/data-table-state.controller.ts
4398
+ function _ts_decorate29(decorators, target, key, desc2) {
4399
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4400
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4401
+ 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;
4402
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4403
+ }
4404
+ __name(_ts_decorate29, "_ts_decorate");
4405
+ function _ts_metadata19(k, v) {
4406
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4407
+ }
4408
+ __name(_ts_metadata19, "_ts_metadata");
4409
+ function _ts_param8(paramIndex, decorator) {
4410
+ return function(target, key) {
4411
+ decorator(target, key, paramIndex);
4412
+ };
4413
+ }
4414
+ __name(_ts_param8, "_ts_param");
4415
+ var DataTableStateController = class _DataTableStateController {
4416
+ static {
4417
+ __name(this, "DataTableStateController");
4418
+ }
4419
+ dataTableStateService;
4420
+ logger = new Logger14(_DataTableStateController.name);
4421
+ constructor(dataTableStateService) {
4422
+ this.dataTableStateService = dataTableStateService;
4423
+ }
4424
+ // Saves live table state to Redis cache for the authenticated user's table
4425
+ upsertCurrentState(userId, dto) {
4426
+ this.logger.log(`POST /table-states - User: ${userId}, table: ${dto.tableSlug}`);
4427
+ return this.dataTableStateService.upsertCurrentState(userId, dto);
4428
+ }
4429
+ };
4430
+ _ts_decorate29([
4431
+ Post(),
4432
+ HttpCode2(HttpStatus21.OK),
4433
+ ApiUpsertDataTableState(),
4434
+ _ts_param8(0, UserId()),
4435
+ _ts_param8(1, Body()),
4436
+ _ts_metadata19("design:type", Function),
4437
+ _ts_metadata19("design:paramtypes", [
4438
+ String,
4439
+ typeof UpsertDataTableStateDto === "undefined" ? Object : UpsertDataTableStateDto
4440
+ ]),
4441
+ _ts_metadata19("design:returntype", typeof Promise === "undefined" ? Object : Promise)
4442
+ ], DataTableStateController.prototype, "upsertCurrentState", null);
4443
+ DataTableStateController = _ts_decorate29([
4444
+ ApiTags3("Table States"),
4445
+ ApiBearerAuth(),
4446
+ Controller3("table-states"),
4447
+ _ts_metadata19("design:type", Function),
4448
+ _ts_metadata19("design:paramtypes", [
4449
+ typeof DataTableStateService === "undefined" ? Object : DataTableStateService
4450
+ ])
4451
+ ], DataTableStateController);
4452
+
4453
+ // src/data-table/views/controllers/data-table-views.controller.ts
4454
+ import { Body as Body2, Controller as Controller4, Delete, Get as Get3, HttpCode as HttpCode3, HttpStatus as HttpStatus22, Logger as Logger16, Param, Patch, Post as Post2, Query } from "@nestjs/common";
4455
+ import { ApiBearerAuth as ApiBearerAuth2, ApiTags as ApiTags4 } from "@nestjs/swagger";
4456
+
4457
+ // src/data-table/views/docs/data-table-views.docs.ts
4458
+ import { applyDecorators as applyDecorators4 } from "@nestjs/common";
4459
+ import { ApiBody as ApiBody2, ApiOperation as ApiOperation4, ApiParam, ApiQuery, ApiResponse as ApiResponse4 } from "@nestjs/swagger";
4460
+
4461
+ // src/data-table/views/dto/entity/data-table-view.dto.ts
4462
+ import { ApiProperty as ApiProperty4, ApiPropertyOptional as ApiPropertyOptional4 } from "@nestjs/swagger";
4463
+ function _ts_decorate30(decorators, target, key, desc2) {
4464
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4465
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4466
+ 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;
4467
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4468
+ }
4469
+ __name(_ts_decorate30, "_ts_decorate");
4470
+ function _ts_metadata20(k, v) {
4471
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4472
+ }
4473
+ __name(_ts_metadata20, "_ts_metadata");
4474
+ var DataTableViewDto = class _DataTableViewDto {
4475
+ static {
4476
+ __name(this, "DataTableViewDto");
4477
+ }
4478
+ id;
4479
+ name;
4480
+ tableSlug;
4481
+ state;
4482
+ isShared;
4483
+ isOwn;
4484
+ createdAt;
4485
+ updatedAt;
4486
+ // Creates a response DTO from a DataTableView entity, computing isOwn by comparing userId
4487
+ static from(view, userId) {
4488
+ const dto = new _DataTableViewDto();
4489
+ dto.id = view.id;
4490
+ dto.name = view.name ?? null;
4491
+ dto.tableSlug = view.tableSlug;
4492
+ dto.state = view.state;
4493
+ dto.isShared = view.isShared;
4494
+ dto.isOwn = view.userId === userId;
4495
+ dto.createdAt = view.createdAt;
4496
+ dto.updatedAt = view.updatedAt ?? null;
4497
+ return dto;
4498
+ }
4499
+ };
4500
+ _ts_decorate30([
4501
+ ApiProperty4({
4502
+ description: "View unique identifier"
4503
+ }),
4504
+ _ts_metadata20("design:type", String)
4505
+ ], DataTableViewDto.prototype, "id", void 0);
4506
+ _ts_decorate30([
4507
+ ApiPropertyOptional4({
4508
+ description: "Display name of the view",
4509
+ nullable: true
4510
+ }),
4511
+ _ts_metadata20("design:type", Object)
4512
+ ], DataTableViewDto.prototype, "name", void 0);
4513
+ _ts_decorate30([
4514
+ ApiProperty4({
4515
+ description: "Slug of the table this view belongs to",
4516
+ example: "cloud-providers"
4517
+ }),
4518
+ _ts_metadata20("design:type", String)
4519
+ ], DataTableViewDto.prototype, "tableSlug", void 0);
4520
+ _ts_decorate30([
4521
+ ApiProperty4({
4522
+ description: "Stored filter, sort, and column visibility state"
4523
+ }),
4524
+ _ts_metadata20("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4525
+ ], DataTableViewDto.prototype, "state", void 0);
4526
+ _ts_decorate30([
4527
+ ApiProperty4({
4528
+ description: "Whether the view is visible to all users",
4529
+ example: false
4530
+ }),
4531
+ _ts_metadata20("design:type", Boolean)
4532
+ ], DataTableViewDto.prototype, "isShared", void 0);
4533
+ _ts_decorate30([
4534
+ ApiProperty4({
4535
+ description: "Whether the requesting user owns this view",
4536
+ example: true
4537
+ }),
4538
+ _ts_metadata20("design:type", Boolean)
4539
+ ], DataTableViewDto.prototype, "isOwn", void 0);
4540
+ _ts_decorate30([
4541
+ ApiProperty4({
4542
+ description: "Creation timestamp"
4543
+ }),
4544
+ _ts_metadata20("design:type", typeof Date === "undefined" ? Object : Date)
4545
+ ], DataTableViewDto.prototype, "createdAt", void 0);
4546
+ _ts_decorate30([
4547
+ ApiPropertyOptional4({
4548
+ description: "Last updated timestamp",
4549
+ nullable: true
4550
+ }),
4551
+ _ts_metadata20("design:type", Object)
4552
+ ], DataTableViewDto.prototype, "updatedAt", void 0);
4553
+
4554
+ // src/data-table/views/dto/request/create-data-table-view.dto.ts
4555
+ import { ApiProperty as ApiProperty5, ApiPropertyOptional as ApiPropertyOptional5 } from "@nestjs/swagger";
4556
+ import { IsBoolean as IsBoolean2, IsObject as IsObject2, IsOptional as IsOptional3, IsString as IsString4, MaxLength as MaxLength2 } from "class-validator";
4557
+ function _ts_decorate31(decorators, target, key, desc2) {
4558
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4559
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4560
+ 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;
4561
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4562
+ }
4563
+ __name(_ts_decorate31, "_ts_decorate");
4564
+ function _ts_metadata21(k, v) {
4565
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4566
+ }
4567
+ __name(_ts_metadata21, "_ts_metadata");
4568
+ var CreateDataTableViewDto = class {
4569
+ static {
4570
+ __name(this, "CreateDataTableViewDto");
4571
+ }
4572
+ name;
4573
+ tableSlug;
4574
+ state;
4575
+ isShared;
4576
+ };
4577
+ _ts_decorate31([
4578
+ ApiProperty5({
4579
+ description: "Display name for the saved view",
4580
+ example: "AWS Only"
4581
+ }),
4582
+ IsString4(),
4583
+ MaxLength2(100),
4584
+ _ts_metadata21("design:type", String)
4585
+ ], CreateDataTableViewDto.prototype, "name", void 0);
4586
+ _ts_decorate31([
4587
+ ApiProperty5({
4588
+ description: "Unique slug identifying the table",
4589
+ example: "cloud-providers"
4590
+ }),
4591
+ IsString4(),
4592
+ MaxLength2(100),
4593
+ _ts_metadata21("design:type", String)
4594
+ ], CreateDataTableViewDto.prototype, "tableSlug", void 0);
4595
+ _ts_decorate31([
4596
+ ApiProperty5({
4597
+ description: "Full table view state including filters, sort, and column visibility"
4598
+ }),
4599
+ IsObject2(),
4600
+ _ts_metadata21("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4601
+ ], CreateDataTableViewDto.prototype, "state", void 0);
4602
+ _ts_decorate31([
4603
+ ApiPropertyOptional5({
4604
+ description: "Whether this view is visible to all users",
4605
+ example: false
4606
+ }),
4607
+ IsBoolean2(),
4608
+ IsOptional3(),
4609
+ _ts_metadata21("design:type", Boolean)
4610
+ ], CreateDataTableViewDto.prototype, "isShared", void 0);
4611
+
4612
+ // src/data-table/views/dto/request/rename-data-table-view.dto.ts
4613
+ import { ApiProperty as ApiProperty6 } from "@nestjs/swagger";
4614
+ import { IsString as IsString5, MaxLength as MaxLength3, MinLength } from "class-validator";
4615
+ function _ts_decorate32(decorators, target, key, desc2) {
4616
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4617
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4618
+ 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;
4619
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4620
+ }
4621
+ __name(_ts_decorate32, "_ts_decorate");
4622
+ function _ts_metadata22(k, v) {
4623
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4624
+ }
4625
+ __name(_ts_metadata22, "_ts_metadata");
4626
+ var RenameDataTableViewDto = class {
4627
+ static {
4628
+ __name(this, "RenameDataTableViewDto");
4629
+ }
4630
+ name;
4631
+ };
4632
+ _ts_decorate32([
4633
+ ApiProperty6({
4634
+ description: "New display name for the view",
4635
+ example: "AWS Only"
4636
+ }),
4637
+ IsString5(),
4638
+ MinLength(1),
4639
+ MaxLength3(100),
4640
+ _ts_metadata22("design:type", String)
4641
+ ], RenameDataTableViewDto.prototype, "name", void 0);
4642
+
4643
+ // src/data-table/views/dto/request/toggle-share-data-table-view.dto.ts
4644
+ import { ApiProperty as ApiProperty7 } from "@nestjs/swagger";
4645
+ import { IsBoolean as IsBoolean3 } from "class-validator";
4646
+ function _ts_decorate33(decorators, target, key, desc2) {
4647
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4648
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4649
+ 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;
4650
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4651
+ }
4652
+ __name(_ts_decorate33, "_ts_decorate");
4653
+ function _ts_metadata23(k, v) {
4654
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4655
+ }
4656
+ __name(_ts_metadata23, "_ts_metadata");
4657
+ var ToggleShareDataTableViewDto = class {
4658
+ static {
4659
+ __name(this, "ToggleShareDataTableViewDto");
4660
+ }
4661
+ isShared;
4662
+ };
4663
+ _ts_decorate33([
4664
+ ApiProperty7({
4665
+ description: "Whether the view should be visible to all users",
4666
+ example: true
4667
+ }),
4668
+ IsBoolean3(),
4669
+ _ts_metadata23("design:type", Boolean)
4670
+ ], ToggleShareDataTableViewDto.prototype, "isShared", void 0);
4671
+
4672
+ // src/data-table/views/dto/request/update-data-table-view.dto.ts
4673
+ import { ApiProperty as ApiProperty8 } from "@nestjs/swagger";
4674
+ import { IsObject as IsObject3 } from "class-validator";
4675
+ function _ts_decorate34(decorators, target, key, desc2) {
4676
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4677
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4678
+ 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;
4679
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4680
+ }
4681
+ __name(_ts_decorate34, "_ts_decorate");
4682
+ function _ts_metadata24(k, v) {
4683
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4684
+ }
4685
+ __name(_ts_metadata24, "_ts_metadata");
4686
+ var UpdateDataTableViewDto = class {
4687
+ static {
4688
+ __name(this, "UpdateDataTableViewDto");
4689
+ }
4690
+ state;
4691
+ };
4692
+ _ts_decorate34([
4693
+ ApiProperty8({
4694
+ description: "Updated filter, sort, and column visibility state"
4695
+ }),
4696
+ IsObject3(),
4697
+ _ts_metadata24("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
4698
+ ], UpdateDataTableViewDto.prototype, "state", void 0);
4699
+
4700
+ // src/data-table/views/docs/data-table-views.docs.ts
4701
+ function ApiListDataTableViews() {
4702
+ return applyDecorators4(ApiOperation4({
4703
+ summary: "List named table views",
4704
+ description: "Returns the authenticated user's own named views plus all shared views for the given table slug."
4705
+ }), ApiQuery({
4706
+ name: "tableSlug",
4707
+ description: "Slug of the table to fetch views for",
4708
+ example: "cloud-providers",
4709
+ required: true
4710
+ }), ApiResponse4({
4711
+ status: 200,
4712
+ description: "Named views retrieved.",
4713
+ type: [
4714
+ DataTableViewDto
4715
+ ]
4716
+ }), ApiResponse4({
4717
+ status: 401,
4718
+ description: "Unauthorized."
4719
+ }));
4720
+ }
4721
+ __name(ApiListDataTableViews, "ApiListDataTableViews");
4722
+ function ApiCreateDataTableView() {
4723
+ return applyDecorators4(ApiOperation4({
4724
+ summary: "Create named table view",
4725
+ description: "Saves the current table state as a named view snapshot. The name must be unique per user+table."
4726
+ }), ApiBody2({
4727
+ type: CreateDataTableViewDto
4728
+ }), ApiResponse4({
4729
+ status: 201,
4730
+ description: "Named view created.",
4731
+ type: DataTableViewDto
4732
+ }), ApiResponse4({
4733
+ status: 400,
4734
+ description: "Invalid request body."
4735
+ }), ApiResponse4({
4736
+ status: 401,
4737
+ description: "Unauthorized."
4738
+ }));
4739
+ }
4740
+ __name(ApiCreateDataTableView, "ApiCreateDataTableView");
4741
+ function ApiUpdateDataTableView() {
4742
+ return applyDecorators4(ApiOperation4({
4743
+ summary: "Update named table view",
4744
+ description: "Updates the state of an existing named view. Only the owner can update."
4745
+ }), ApiParam({
4746
+ name: "id",
4747
+ description: "UUID of the table view to update"
4748
+ }), ApiBody2({
4749
+ type: UpdateDataTableViewDto
4750
+ }), ApiResponse4({
4751
+ status: 200,
4752
+ description: "View updated.",
4753
+ type: DataTableViewDto
4754
+ }), ApiResponse4({
4755
+ status: 400,
4756
+ description: "Validation failed or not owned by caller."
4757
+ }), ApiResponse4({
4758
+ status: 401,
4759
+ description: "Unauthorized."
4760
+ }), ApiResponse4({
4761
+ status: 404,
4762
+ description: "View not found."
4763
+ }));
4764
+ }
4765
+ __name(ApiUpdateDataTableView, "ApiUpdateDataTableView");
4766
+ function ApiRenameDataTableView() {
4767
+ return applyDecorators4(ApiOperation4({
4768
+ summary: "Rename a named table view",
4769
+ description: "Updates the display name of an existing view. The new name must be unique per user+table. Only the owner can rename."
4770
+ }), ApiParam({
4771
+ name: "id",
4772
+ description: "UUID of the table view to rename"
4773
+ }), ApiBody2({
4774
+ type: RenameDataTableViewDto
4775
+ }), ApiResponse4({
4776
+ status: 200,
4777
+ description: "View renamed.",
4778
+ type: DataTableViewDto
4779
+ }), ApiResponse4({
4780
+ status: 400,
4781
+ description: "Not owned by caller."
4782
+ }), ApiResponse4({
4783
+ status: 401,
4784
+ description: "Unauthorized."
4785
+ }), ApiResponse4({
4786
+ status: 404,
4787
+ description: "View not found."
4788
+ }), ApiResponse4({
4789
+ status: 409,
4790
+ description: "A view with this name already exists."
4791
+ }));
4792
+ }
4793
+ __name(ApiRenameDataTableView, "ApiRenameDataTableView");
4794
+ function ApiToggleShareDataTableView() {
4795
+ return applyDecorators4(ApiOperation4({
4796
+ summary: "Toggle view sharing",
4797
+ description: "Makes a view visible to all users (shared) or restricts it to the owner only (private). Only the owner can toggle sharing."
4798
+ }), ApiParam({
4799
+ name: "id",
4800
+ description: "UUID of the table view"
4801
+ }), ApiBody2({
4802
+ type: ToggleShareDataTableViewDto
4803
+ }), ApiResponse4({
4804
+ status: 200,
4805
+ description: "Sharing status updated.",
4806
+ type: DataTableViewDto
4807
+ }), ApiResponse4({
4808
+ status: 400,
4809
+ description: "Not owned by caller."
4810
+ }), ApiResponse4({
4811
+ status: 401,
4812
+ description: "Unauthorized."
4813
+ }), ApiResponse4({
4814
+ status: 404,
4815
+ description: "View not found."
4816
+ }));
4817
+ }
4818
+ __name(ApiToggleShareDataTableView, "ApiToggleShareDataTableView");
4819
+ function ApiDeleteDataTableView() {
4820
+ return applyDecorators4(ApiOperation4({
4821
+ summary: "Delete named table view",
4822
+ description: "Permanently deletes a named view. Only the owner can delete their own views."
4823
+ }), ApiParam({
4824
+ name: "id",
4825
+ description: "UUID of the table view to delete"
4826
+ }), ApiResponse4({
4827
+ status: 200,
4828
+ description: "View deleted.",
4829
+ type: DataTableViewDto
4830
+ }), ApiResponse4({
4831
+ status: 400,
4832
+ description: "Not owned by caller."
4833
+ }), ApiResponse4({
4834
+ status: 401,
4835
+ description: "Unauthorized."
4836
+ }), ApiResponse4({
4837
+ status: 404,
4838
+ description: "View not found."
4839
+ }));
4840
+ }
4841
+ __name(ApiDeleteDataTableView, "ApiDeleteDataTableView");
4842
+
4843
+ // src/data-table/views/services/data-table-views.service.ts
4844
+ import { createHash as createHash2 } from "crypto";
4845
+ import { Injectable as Injectable16, Logger as Logger15 } from "@nestjs/common";
4846
+ import { ConfigService as ConfigService7 } from "@nestjs/config";
4847
+
4848
+ // src/data-table/views/repositories/data-table-views.repository.ts
4849
+ import { Inject as Inject5, Injectable as Injectable15 } from "@nestjs/common";
4850
+ import { and as and4, eq as eq5 } from "drizzle-orm";
4851
+ function _ts_decorate35(decorators, target, key, desc2) {
4852
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4853
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4854
+ 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;
4855
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4856
+ }
4857
+ __name(_ts_decorate35, "_ts_decorate");
4858
+ function _ts_metadata25(k, v) {
4859
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4860
+ }
4861
+ __name(_ts_metadata25, "_ts_metadata");
4862
+ function _ts_param9(paramIndex, decorator) {
4863
+ return function(target, key) {
4864
+ decorator(target, key, paramIndex);
4865
+ };
4866
+ }
4867
+ __name(_ts_param9, "_ts_param");
4868
+ var NAMED_VIEWS_LIMIT = 100;
4869
+ var DataTableViewsRepository = class extends PrimaryBaseRepository {
4870
+ static {
4871
+ __name(this, "DataTableViewsRepository");
4872
+ }
4873
+ constructor(database, table) {
4874
+ super(database, table);
4875
+ }
4876
+ // Returns personal (non-shared) named views owned by the user for a given table
4877
+ async findPersonalViewsBySlug(userId, tableSlug) {
4878
+ const t = this.table;
4879
+ return this.db.select().from(this.table).where(and4(eq5(t.tableSlug, tableSlug), eq5(t.userId, userId), eq5(t.isShared, false))).orderBy(t.createdAt).limit(NAMED_VIEWS_LIMIT);
4880
+ }
4881
+ // Returns all shared named views for a given table — visible to all users
4882
+ async findSharedViewsBySlug(tableSlug) {
4883
+ const t = this.table;
4884
+ return this.db.select().from(this.table).where(and4(eq5(t.tableSlug, tableSlug), eq5(t.isShared, true))).orderBy(t.createdAt).limit(NAMED_VIEWS_LIMIT);
4885
+ }
4886
+ };
4887
+ DataTableViewsRepository = _ts_decorate35([
4888
+ Injectable15(),
4889
+ _ts_param9(1, Inject5(DATA_TABLE_VIEWS_TABLE)),
4890
+ _ts_metadata25("design:type", Function),
4891
+ _ts_metadata25("design:paramtypes", [
4892
+ typeof PrimaryDatabaseService === "undefined" ? Object : PrimaryDatabaseService,
4893
+ typeof PgTable === "undefined" ? Object : PgTable
4894
+ ])
4895
+ ], DataTableViewsRepository);
4896
+
4897
+ // src/data-table/views/services/data-table-views.service.ts
4898
+ function _ts_decorate36(decorators, target, key, desc2) {
4899
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
4900
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
4901
+ 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;
4902
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4903
+ }
4904
+ __name(_ts_decorate36, "_ts_decorate");
4905
+ function _ts_metadata26(k, v) {
4906
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4907
+ }
4908
+ __name(_ts_metadata26, "_ts_metadata");
4909
+ function computeChecksum(value) {
4910
+ return createHash2("sha256").update(JSON.stringify(value)).digest("hex");
4911
+ }
4912
+ __name(computeChecksum, "computeChecksum");
4913
+ var DataTableViewsService = class _DataTableViewsService {
4914
+ static {
4915
+ __name(this, "DataTableViewsService");
4916
+ }
4917
+ dataTableViewsRepository;
4918
+ cacheService;
4919
+ configService;
4920
+ logger = new Logger15(_DataTableViewsService.name);
4921
+ constructor(dataTableViewsRepository, cacheService, configService) {
4922
+ this.dataTableViewsRepository = dataTableViewsRepository;
4923
+ this.cacheService = cacheService;
4924
+ this.configService = configService;
4925
+ }
4926
+ // Builds the Redis key for a user's personal (non-shared) views for a given table
4927
+ personalViewsKey(userId, tableSlug) {
4928
+ return `views:personal:${userId}:${tableSlug}`;
4929
+ }
4930
+ // Builds the Redis key for all shared views for a given table — same key for all users
4931
+ sharedViewsKey(tableSlug) {
4932
+ return `views:shared:${tableSlug}`;
4933
+ }
4934
+ // Returns configured TTL for named views in seconds, defaulting to 86400 (24h)
4935
+ get viewsTtl() {
4936
+ return this.configService.get("TABLE_VIEWS_CACHE_TTL") ?? 86400;
4937
+ }
4938
+ // Fetches personal views from cache; falls back to DB and warms cache on miss
4939
+ async getOrCachePersonalViews(userId, tableSlug) {
4940
+ const key = this.personalViewsKey(userId, tableSlug);
4941
+ const cached = await this.cacheService.get(key);
4942
+ if (cached) {
4943
+ this.logger.debug(`Cache hit for personal views: user=${userId}, table=${tableSlug}`);
4944
+ return cached;
4945
+ }
4946
+ const rows = await this.dataTableViewsRepository.findPersonalViewsBySlug(userId, tableSlug);
4947
+ await this.cacheService.set(key, rows, this.viewsTtl);
4948
+ return rows;
4949
+ }
4950
+ // Fetches shared views from cache; falls back to DB and warms cache on miss
4951
+ async getOrCacheSharedViews(tableSlug) {
4952
+ const key = this.sharedViewsKey(tableSlug);
4953
+ const cached = await this.cacheService.get(key);
4954
+ if (cached) {
4955
+ this.logger.debug(`Cache hit for shared views: table=${tableSlug}`);
4956
+ return cached;
4957
+ }
4958
+ const rows = await this.dataTableViewsRepository.findSharedViewsBySlug(tableSlug);
4959
+ await this.cacheService.set(key, rows, this.viewsTtl);
4960
+ return rows;
4961
+ }
4962
+ // Deletes personal and/or shared cache keys based on which pools the mutation affects
4963
+ async invalidateViewsCache(userId, tableSlug, affectsPersonal, affectsShared) {
4964
+ const toDelete = [];
4965
+ if (affectsPersonal) toDelete.push(this.personalViewsKey(userId, tableSlug));
4966
+ if (affectsShared) toDelete.push(this.sharedViewsKey(tableSlug));
4967
+ if (toDelete.length > 0) await this.cacheService.del(...toDelete);
4968
+ }
4969
+ // Returns personal + shared named views — each pool fetched from cache or DB in parallel
4970
+ async findViews(userId, tableSlug) {
4971
+ const [personalRows, sharedRows] = await Promise.all([
4972
+ this.getOrCachePersonalViews(userId, tableSlug),
4973
+ this.getOrCacheSharedViews(tableSlug)
4974
+ ]);
4975
+ return [
4976
+ ...personalRows,
4977
+ ...sharedRows
4978
+ ].map((row) => DataTableViewDto.from(row, userId));
4979
+ }
4980
+ // Creates a named snapshot and invalidates the relevant cache pool
4981
+ async createView(userId, dto) {
4982
+ const view = await this.dataTableViewsRepository.create({
4983
+ userId,
4984
+ tableSlug: dto.tableSlug,
4985
+ name: dto.name,
4986
+ state: dto.state,
4987
+ isShared: dto.isShared ?? false
4988
+ });
4989
+ this.logger.log(`Created view "${dto.name}" for user: ${userId}, table: ${dto.tableSlug}`);
4990
+ const isShared = dto.isShared ?? false;
4991
+ await this.invalidateViewsCache(userId, dto.tableSlug, !isShared, isShared);
4992
+ return DataTableViewDto.from(view, userId);
4993
+ }
4994
+ // Updates the state of a named view — skips DB write if state is unchanged
4995
+ async updateView(userId, id, dto) {
4996
+ const view = await this.dataTableViewsRepository.findById(id);
4997
+ if (!view) throw new NotFoundException("Table view not found.");
4998
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to update this view.");
4999
+ if (computeChecksum(dto.state) === computeChecksum(view.state)) {
5000
+ this.logger.log(`State unchanged for view ${id} \u2014 skipping DB write`);
5001
+ return DataTableViewDto.from(view, userId);
5002
+ }
5003
+ const updated = await this.dataTableViewsRepository.update(id, {
5004
+ state: dto.state
5005
+ });
5006
+ this.logger.log(`Updated state for view ${id}, user: ${userId}`);
5007
+ await this.invalidateViewsCache(userId, view.tableSlug, !view.isShared, view.isShared);
5008
+ return DataTableViewDto.from(updated, userId);
5009
+ }
5010
+ // Toggles the sharing status of a named view — updates both personal and shared cache
5011
+ async toggleShareView(userId, id, isShared) {
5012
+ const view = await this.dataTableViewsRepository.findById(id);
5013
+ if (!view) throw new NotFoundException("Table view not found.");
5014
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to share this view.");
5015
+ const updated = await this.dataTableViewsRepository.update(id, {
5016
+ isShared
5017
+ });
5018
+ this.logger.log(`Set isShared=${isShared} for view ${id}, user: ${userId}`);
5019
+ await this.invalidateViewsCache(userId, view.tableSlug, true, true);
5020
+ return DataTableViewDto.from(updated, userId);
5021
+ }
5022
+ // Renames a named view — enforces unique name per user+table, invalidates personal cache
5023
+ async renameView(userId, id, name) {
5024
+ const view = await this.dataTableViewsRepository.findById(id);
5025
+ if (!view) throw new NotFoundException("Table view not found.");
5026
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to rename this view.");
5027
+ const existing = await this.dataTableViewsRepository.findOne({
5028
+ userId,
5029
+ tableSlug: view.tableSlug,
5030
+ name,
5031
+ isShared: false
5032
+ });
5033
+ if (existing && existing.id !== id) {
5034
+ throw new ConflictException({
5035
+ label: "Name Already Taken",
5036
+ detail: "A view with this name already exists for this table.",
5037
+ errors: [
5038
+ {
5039
+ field: "name",
5040
+ message: "Name already taken"
5041
+ }
5042
+ ]
5043
+ });
5044
+ }
5045
+ const updated = await this.dataTableViewsRepository.update(id, {
5046
+ name
5047
+ });
5048
+ this.logger.log(`Renamed view ${id} to "${name}" for user: ${userId}`);
5049
+ await this.invalidateViewsCache(userId, view.tableSlug, !view.isShared, view.isShared);
5050
+ return DataTableViewDto.from(updated, userId);
5051
+ }
5052
+ // Deletes a named view and invalidates the relevant cache pool
5053
+ async deleteView(userId, id) {
5054
+ const view = await this.dataTableViewsRepository.findById(id);
5055
+ if (!view) throw new NotFoundException("Table view not found.");
5056
+ if (view.userId !== userId) throw new BadRequestException("You do not have permission to delete this view.");
5057
+ await this.dataTableViewsRepository.delete(id);
5058
+ this.logger.log(`Deleted view ${id} for user: ${userId}`);
5059
+ await this.invalidateViewsCache(userId, view.tableSlug, !view.isShared, view.isShared);
5060
+ return DataTableViewDto.from(view, userId);
5061
+ }
5062
+ };
5063
+ DataTableViewsService = _ts_decorate36([
5064
+ Injectable16(),
5065
+ _ts_metadata26("design:type", Function),
5066
+ _ts_metadata26("design:paramtypes", [
5067
+ typeof DataTableViewsRepository === "undefined" ? Object : DataTableViewsRepository,
5068
+ typeof CacheService === "undefined" ? Object : CacheService,
5069
+ typeof ConfigService7 === "undefined" ? Object : ConfigService7
5070
+ ])
5071
+ ], DataTableViewsService);
5072
+
5073
+ // src/data-table/views/controllers/data-table-views.controller.ts
5074
+ function _ts_decorate37(decorators, target, key, desc2) {
5075
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
5076
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
5077
+ 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;
5078
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
5079
+ }
5080
+ __name(_ts_decorate37, "_ts_decorate");
5081
+ function _ts_metadata27(k, v) {
5082
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5083
+ }
5084
+ __name(_ts_metadata27, "_ts_metadata");
5085
+ function _ts_param10(paramIndex, decorator) {
5086
+ return function(target, key) {
5087
+ decorator(target, key, paramIndex);
5088
+ };
5089
+ }
5090
+ __name(_ts_param10, "_ts_param");
5091
+ var DataTableViewsController = class _DataTableViewsController {
5092
+ static {
5093
+ __name(this, "DataTableViewsController");
5094
+ }
5095
+ dataTableViewsService;
5096
+ logger = new Logger16(_DataTableViewsController.name);
5097
+ constructor(dataTableViewsService) {
5098
+ this.dataTableViewsService = dataTableViewsService;
5099
+ }
5100
+ // Returns all named views for the given table — own plus shared
5101
+ findViews(userId, tableSlug) {
5102
+ this.logger.log(`GET /table-views?tableSlug=${tableSlug} - User: ${userId}`);
5103
+ return this.dataTableViewsService.findViews(userId, tableSlug);
5104
+ }
5105
+ // Creates a named snapshot of the current table state
5106
+ createView(userId, dto) {
5107
+ this.logger.log(`POST /table-views - User: ${userId}, table: ${dto.tableSlug}`);
5108
+ return this.dataTableViewsService.createView(userId, dto);
5109
+ }
5110
+ // Updates state of an existing named view
5111
+ updateView(userId, id, dto) {
5112
+ this.logger.log(`PATCH /table-views/${id} - User: ${userId}`);
5113
+ return this.dataTableViewsService.updateView(userId, id, dto);
5114
+ }
5115
+ // Renames an existing named view — enforces unique name per user+table
5116
+ renameView(userId, id, dto) {
5117
+ this.logger.log(`PATCH /table-views/${id}/rename - User: ${userId}`);
5118
+ return this.dataTableViewsService.renameView(userId, id, dto.name);
5119
+ }
5120
+ // Toggles sharing visibility of a named view
5121
+ toggleShareView(userId, id, dto) {
5122
+ this.logger.log(`PATCH /table-views/${id}/share - User: ${userId}`);
5123
+ return this.dataTableViewsService.toggleShareView(userId, id, dto.isShared);
5124
+ }
5125
+ // Deletes a named view owned by the authenticated user
5126
+ deleteView(userId, id) {
5127
+ this.logger.log(`DELETE /table-views/${id} - User: ${userId}`);
5128
+ return this.dataTableViewsService.deleteView(userId, id);
5129
+ }
5130
+ };
5131
+ _ts_decorate37([
5132
+ Get3(),
5133
+ ApiListDataTableViews(),
5134
+ _ts_param10(0, UserId()),
5135
+ _ts_param10(1, Query("tableSlug")),
5136
+ _ts_metadata27("design:type", Function),
5137
+ _ts_metadata27("design:paramtypes", [
5138
+ String,
5139
+ String
5140
+ ]),
5141
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5142
+ ], DataTableViewsController.prototype, "findViews", null);
5143
+ _ts_decorate37([
5144
+ Post2(),
5145
+ HttpCode3(HttpStatus22.CREATED),
5146
+ ApiCreateDataTableView(),
5147
+ _ts_param10(0, UserId()),
5148
+ _ts_param10(1, Body2()),
5149
+ _ts_metadata27("design:type", Function),
5150
+ _ts_metadata27("design:paramtypes", [
5151
+ String,
5152
+ typeof CreateDataTableViewDto === "undefined" ? Object : CreateDataTableViewDto
5153
+ ]),
5154
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5155
+ ], DataTableViewsController.prototype, "createView", null);
5156
+ _ts_decorate37([
5157
+ Patch(":id"),
5158
+ ApiUpdateDataTableView(),
5159
+ _ts_param10(0, UserId()),
5160
+ _ts_param10(1, Param("id")),
5161
+ _ts_param10(2, Body2()),
5162
+ _ts_metadata27("design:type", Function),
5163
+ _ts_metadata27("design:paramtypes", [
5164
+ String,
5165
+ String,
5166
+ typeof UpdateDataTableViewDto === "undefined" ? Object : UpdateDataTableViewDto
5167
+ ]),
5168
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5169
+ ], DataTableViewsController.prototype, "updateView", null);
5170
+ _ts_decorate37([
5171
+ Patch(":id/rename"),
5172
+ ApiRenameDataTableView(),
5173
+ _ts_param10(0, UserId()),
5174
+ _ts_param10(1, Param("id")),
5175
+ _ts_param10(2, Body2()),
5176
+ _ts_metadata27("design:type", Function),
5177
+ _ts_metadata27("design:paramtypes", [
5178
+ String,
5179
+ String,
5180
+ typeof RenameDataTableViewDto === "undefined" ? Object : RenameDataTableViewDto
5181
+ ]),
5182
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5183
+ ], DataTableViewsController.prototype, "renameView", null);
5184
+ _ts_decorate37([
5185
+ Patch(":id/share"),
5186
+ ApiToggleShareDataTableView(),
5187
+ _ts_param10(0, UserId()),
5188
+ _ts_param10(1, Param("id")),
5189
+ _ts_param10(2, Body2()),
5190
+ _ts_metadata27("design:type", Function),
5191
+ _ts_metadata27("design:paramtypes", [
5192
+ String,
5193
+ String,
5194
+ typeof ToggleShareDataTableViewDto === "undefined" ? Object : ToggleShareDataTableViewDto
5195
+ ]),
5196
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5197
+ ], DataTableViewsController.prototype, "toggleShareView", null);
5198
+ _ts_decorate37([
5199
+ Delete(":id"),
5200
+ ApiDeleteDataTableView(),
5201
+ _ts_param10(0, UserId()),
5202
+ _ts_param10(1, Param("id")),
5203
+ _ts_metadata27("design:type", Function),
5204
+ _ts_metadata27("design:paramtypes", [
5205
+ String,
5206
+ String
5207
+ ]),
5208
+ _ts_metadata27("design:returntype", typeof Promise === "undefined" ? Object : Promise)
5209
+ ], DataTableViewsController.prototype, "deleteView", null);
5210
+ DataTableViewsController = _ts_decorate37([
5211
+ ApiTags4("Table Views"),
5212
+ ApiBearerAuth2(),
5213
+ Controller4("table-views"),
5214
+ _ts_metadata27("design:type", Function),
5215
+ _ts_metadata27("design:paramtypes", [
5216
+ typeof DataTableViewsService === "undefined" ? Object : DataTableViewsService
5217
+ ])
5218
+ ], DataTableViewsController);
5219
+
5220
+ // src/data-table/data-table.module.ts
5221
+ function _ts_decorate38(decorators, target, key, desc2) {
5222
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
5223
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
5224
+ 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;
5225
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
5226
+ }
5227
+ __name(_ts_decorate38, "_ts_decorate");
5228
+ var DataTableModule = class _DataTableModule {
5229
+ static {
5230
+ __name(this, "DataTableModule");
5231
+ }
5232
+ static forRoot(options) {
5233
+ return {
5234
+ global: true,
5235
+ module: _DataTableModule,
5236
+ imports: [
5237
+ ConfigModule4,
5238
+ CacheModule
5239
+ ],
5240
+ controllers: [
5241
+ DataTableStateController,
5242
+ DataTableViewsController
5243
+ ],
5244
+ providers: [
5245
+ {
5246
+ provide: DATA_TABLE_VIEWS_TABLE,
5247
+ useValue: options.tableViews
5248
+ },
5249
+ DataTableViewsService,
5250
+ DataTableViewsRepository,
5251
+ DataTableStateService
5252
+ ],
5253
+ exports: [
5254
+ DataTableViewsService,
5255
+ DataTableStateService
5256
+ ]
5257
+ };
5258
+ }
5259
+ };
5260
+ DataTableModule = _ts_decorate38([
5261
+ Module8({})
5262
+ ], DataTableModule);
5263
+
5264
+ // src/drizzle-pg-core.ts
5265
+ var drizzle_pg_core_exports = {};
5266
+ __reExport(drizzle_pg_core_exports, pg_core_star);
5267
+ import * as pg_core_star from "drizzle-orm/pg-core";
5268
+
5269
+ // src/data-table/schema/data-table-views.table.ts
5270
+ function dataTableViewsColumns() {
5271
+ return {
5272
+ id: (0, drizzle_pg_core_exports.uuid)("id").primaryKey().defaultRandom(),
5273
+ userId: (0, drizzle_pg_core_exports.uuid)("user_id").notNull(),
5274
+ tableSlug: (0, drizzle_pg_core_exports.varchar)("table_slug", {
5275
+ length: 100
5276
+ }).notNull(),
5277
+ name: (0, drizzle_pg_core_exports.varchar)("name", {
5278
+ length: 100
5279
+ }).notNull(),
5280
+ state: (0, drizzle_pg_core_exports.jsonb)("state").notNull().$type(),
5281
+ isShared: (0, drizzle_pg_core_exports.boolean)("is_shared").notNull().default(false),
5282
+ createdAt: (0, drizzle_pg_core_exports.timestamp)("created_at", {
5283
+ withTimezone: true
5284
+ }).notNull().defaultNow(),
5285
+ updatedAt: (0, drizzle_pg_core_exports.timestamp)("updated_at", {
5286
+ withTimezone: true
5287
+ }).$onUpdate(() => /* @__PURE__ */ new Date())
5288
+ };
5289
+ }
5290
+ __name(dataTableViewsColumns, "dataTableViewsColumns");
5291
+ function dataTableViewsIndexes(table) {
5292
+ return [
5293
+ (0, drizzle_pg_core_exports.index)("table_views_user_table_idx").on(table.userId, table.tableSlug),
5294
+ (0, drizzle_pg_core_exports.index)("table_views_shared_slug_idx").on(table.tableSlug, table.isShared),
5295
+ (0, drizzle_pg_core_exports.uniqueIndex)("table_views_user_table_name_shared_unique").on(table.userId, table.tableSlug, table.name, table.isShared)
5296
+ ];
5297
+ }
5298
+ __name(dataTableViewsIndexes, "dataTableViewsIndexes");
4236
5299
  export {
4237
5300
  AccessToken,
4238
5301
  AuthConfigModule,
@@ -4244,7 +5307,13 @@ export {
4244
5307
  ConflictException,
4245
5308
  CookieDomain,
4246
5309
  CorrelationIdMiddleware,
5310
+ CreateDataTableViewDto,
5311
+ DATA_TABLE_VIEWS_TABLE,
4247
5312
  DEFAULT_CORRELATION_HEADER,
5313
+ DataTableModule,
5314
+ DataTableStateService,
5315
+ DataTableViewDto,
5316
+ DataTableViewsService,
4248
5317
  DatabaseModule,
4249
5318
  EmailModule,
4250
5319
  EmailService,
@@ -4272,6 +5341,7 @@ export {
4272
5341
  RedisCacheProvider,
4273
5342
  RefreshCookieOptions,
4274
5343
  RefreshTokenCookie,
5344
+ RenameDataTableViewDto,
4275
5345
  RequestTimeoutException,
4276
5346
  Reset,
4277
5347
  RootModule,
@@ -4286,17 +5356,22 @@ export {
4286
5356
  TenantBaseRepository,
4287
5357
  TenantContextService,
4288
5358
  TenantDatabaseService,
5359
+ ToggleShareDataTableViewDto,
4289
5360
  TokenType,
4290
5361
  TooManyRequestsException,
4291
5362
  UnauthorizedException,
4292
5363
  UnprocessableEntityException,
4293
5364
  UnsupportedMediaTypeException,
5365
+ UpdateDataTableViewDto,
5366
+ UpsertDataTableStateDto,
4294
5367
  UserId,
4295
5368
  ValidationException,
4296
5369
  VrittiAuthGuard,
4297
5370
  addCorrelationIdToResponse,
4298
5371
  configureApiSdk,
4299
5372
  correlationStorage,
5373
+ dataTableViewsColumns,
5374
+ dataTableViewsIndexes,
4300
5375
  defineConfig,
4301
5376
  extractCountryFromPhone,
4302
5377
  generateCorrelationId,