@vritti/api-sdk 0.3.3 → 0.3.5

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.
Files changed (133) hide show
  1. package/dist/auth.cjs +942 -0
  2. package/dist/auth.cjs.map +1 -0
  3. package/dist/auth.d.cts +95 -0
  4. package/dist/auth.d.ts +95 -0
  5. package/dist/auth.js +884 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/cache.cjs +182 -14
  8. package/dist/cache.cjs.map +1 -1
  9. package/dist/cache.d.cts +48 -4
  10. package/dist/cache.d.ts +48 -4
  11. package/dist/cache.js +177 -12
  12. package/dist/cache.js.map +1 -1
  13. package/dist/catalog-resolver.cjs +226 -51
  14. package/dist/catalog-resolver.cjs.map +1 -1
  15. package/dist/catalog-resolver.d.cts +41 -19
  16. package/dist/catalog-resolver.d.ts +41 -19
  17. package/dist/catalog-resolver.js +212 -46
  18. package/dist/catalog-resolver.js.map +1 -1
  19. package/dist/code-pattern-BP4zkNtT.d.cts +12 -0
  20. package/dist/code-pattern-BP4zkNtT.d.ts +12 -0
  21. package/dist/context.cjs +93 -0
  22. package/dist/context.cjs.map +1 -0
  23. package/dist/context.d.cts +19 -0
  24. package/dist/context.d.ts +19 -0
  25. package/dist/context.js +64 -0
  26. package/dist/context.js.map +1 -0
  27. package/dist/countries.cjs +1559 -0
  28. package/dist/countries.cjs.map +1 -0
  29. package/dist/countries.d.cts +13 -0
  30. package/dist/countries.d.ts +13 -0
  31. package/dist/countries.js +1532 -0
  32. package/dist/countries.js.map +1 -0
  33. package/dist/data-table.cjs +1280 -0
  34. package/dist/data-table.cjs.map +1 -0
  35. package/dist/data-table.d.cts +123 -0
  36. package/dist/data-table.d.ts +123 -0
  37. package/dist/data-table.js +1260 -0
  38. package/dist/data-table.js.map +1 -0
  39. package/dist/database.cjs +1510 -0
  40. package/dist/database.cjs.map +1 -0
  41. package/dist/database.d.cts +287 -0
  42. package/dist/database.d.ts +287 -0
  43. package/dist/database.js +1469 -0
  44. package/dist/database.js.map +1 -0
  45. package/dist/decimal.d.cts +0 -1
  46. package/dist/decimal.d.ts +0 -1
  47. package/dist/decorators.cjs +1817 -0
  48. package/dist/decorators.cjs.map +1 -0
  49. package/dist/decorators.d.cts +24 -0
  50. package/dist/decorators.d.ts +24 -0
  51. package/dist/decorators.js +1780 -0
  52. package/dist/decorators.js.map +1 -0
  53. package/dist/drizzle-pg-core.cjs +25 -0
  54. package/dist/drizzle-pg-core.cjs.map +1 -1
  55. package/dist/drizzle-pg-core.d.cts +7 -0
  56. package/dist/drizzle-pg-core.d.ts +7 -0
  57. package/dist/drizzle-pg-core.js +22 -0
  58. package/dist/drizzle-pg-core.js.map +1 -1
  59. package/dist/exceptions.cjs +301 -0
  60. package/dist/exceptions.cjs.map +1 -0
  61. package/dist/exceptions.d.cts +90 -0
  62. package/dist/exceptions.d.ts +90 -0
  63. package/dist/exceptions.js +257 -0
  64. package/dist/exceptions.js.map +1 -0
  65. package/dist/filter.types-PuARU9XD.d.cts +50 -0
  66. package/dist/filter.types-PuARU9XD.d.ts +50 -0
  67. package/dist/filters.cjs +407 -0
  68. package/dist/filters.cjs.map +1 -0
  69. package/dist/filters.d.cts +55 -0
  70. package/dist/filters.d.ts +55 -0
  71. package/dist/filters.js +377 -0
  72. package/dist/filters.js.map +1 -0
  73. package/dist/index.cjs +0 -5423
  74. package/dist/index.cjs.map +1 -1
  75. package/dist/index.d.cts +93 -854
  76. package/dist/index.d.ts +93 -854
  77. package/dist/index.js +0 -5301
  78. package/dist/index.js.map +1 -1
  79. package/dist/is-country.decorator-CcNwSSr5.d.cts +5 -0
  80. package/dist/is-country.decorator-CcNwSSr5.d.ts +5 -0
  81. package/dist/license.d.cts +1 -1
  82. package/dist/license.d.ts +1 -1
  83. package/dist/lodash.cjs.map +1 -1
  84. package/dist/lodash.js.map +1 -1
  85. package/dist/logger.cjs +862 -0
  86. package/dist/logger.cjs.map +1 -0
  87. package/dist/logger.d.cts +118 -0
  88. package/dist/logger.d.ts +118 -0
  89. package/dist/logger.js +816 -0
  90. package/dist/logger.js.map +1 -0
  91. package/dist/migrate.cjs +2 -2
  92. package/dist/migrate.cjs.map +1 -1
  93. package/dist/migrate.d.cts +2 -0
  94. package/dist/migrate.d.ts +2 -0
  95. package/dist/migrate.js +2 -2
  96. package/dist/migrate.js.map +1 -1
  97. package/dist/money.cjs +18 -3
  98. package/dist/money.cjs.map +1 -1
  99. package/dist/money.d.cts +13 -13
  100. package/dist/money.d.ts +13 -13
  101. package/dist/money.js +18 -3
  102. package/dist/money.js.map +1 -1
  103. package/dist/nats.cjs +34 -35
  104. package/dist/nats.cjs.map +1 -1
  105. package/dist/nats.d.cts +14 -14
  106. package/dist/nats.d.ts +14 -14
  107. package/dist/nats.js +32 -33
  108. package/dist/nats.js.map +1 -1
  109. package/dist/root.cjs +225 -0
  110. package/dist/root.cjs.map +1 -0
  111. package/dist/root.d.cts +4 -0
  112. package/dist/root.d.ts +4 -0
  113. package/dist/root.js +200 -0
  114. package/dist/root.js.map +1 -0
  115. package/dist/{types-DQRwj5rr.d.cts → types-C9jPdQqH.d.cts} +32 -6
  116. package/dist/{types-DQRwj5rr.d.ts → types-C9jPdQqH.d.ts} +32 -6
  117. package/dist/types.cjs +19 -0
  118. package/dist/types.cjs.map +1 -0
  119. package/dist/types.d.cts +17 -0
  120. package/dist/types.d.ts +17 -0
  121. package/dist/types.js +1 -0
  122. package/dist/types.js.map +1 -0
  123. package/dist/utils.cjs +273 -0
  124. package/dist/utils.cjs.map +1 -0
  125. package/dist/utils.d.cts +8 -0
  126. package/dist/utils.d.ts +8 -0
  127. package/dist/utils.js +245 -0
  128. package/dist/utils.js.map +1 -0
  129. package/package.json +122 -1
  130. package/dist/cache.service-_SuJIcNA.d.cts +0 -20
  131. package/dist/cache.service-_SuJIcNA.d.ts +0 -20
  132. package/dist/fastify-augmentation-CQPBNS5a.d.cts +0 -105
  133. package/dist/fastify-augmentation-CQPBNS5a.d.ts +0 -105
@@ -0,0 +1,1469 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/database/database.module.ts
5
+ import { Global, Module } from "@nestjs/common";
6
+ import { Reflector } from "@nestjs/core";
7
+
8
+ // src/database/constants.ts
9
+ var DATABASE_MODULE_OPTIONS = Symbol("DATABASE_MODULE_OPTIONS");
10
+
11
+ // src/database/services/primary-database.service.ts
12
+ import { AsyncLocalStorage } from "async_hooks";
13
+ import { Inject, Injectable, InternalServerErrorException, Logger } from "@nestjs/common";
14
+ import { drizzle } from "drizzle-orm/node-postgres";
15
+
16
+ // src/database/services/rls-aware-pool.ts
17
+ import { Pool } from "pg";
18
+ var RlsAwarePool = class extends Pool {
19
+ static {
20
+ __name(this, "RlsAwarePool");
21
+ }
22
+ rlsAls;
23
+ txAls;
24
+ applyRlsContext;
25
+ constructor(options) {
26
+ const { rlsAls, txAls, applyRlsContext, ...poolConfig } = options;
27
+ super(poolConfig);
28
+ this.rlsAls = rlsAls;
29
+ this.txAls = txAls;
30
+ this.applyRlsContext = applyRlsContext;
31
+ }
32
+ // biome-ignore lint/suspicious/noExplicitAny: matches pg.Pool.query overload surface
33
+ query(textOrConfig, values, cb) {
34
+ if (typeof textOrConfig === "function") {
35
+ return super.query(textOrConfig);
36
+ }
37
+ if (textOrConfig && typeof textOrConfig.submit === "function") {
38
+ return super.query(textOrConfig, values, cb);
39
+ }
40
+ if (typeof values === "function" || typeof cb === "function") {
41
+ return super.query(textOrConfig, values, cb);
42
+ }
43
+ const rls = this.rlsAls.getStore();
44
+ if (rls === void 0 || this.txAls.getStore() !== void 0 || !this.applyRlsContext) {
45
+ return super.query(textOrConfig, values);
46
+ }
47
+ return this.runWrapped(textOrConfig, values, rls);
48
+ }
49
+ // biome-ignore lint/suspicious/noExplicitAny: dispatched from query() overload
50
+ async runWrapped(textOrConfig, values, rls) {
51
+ const client = await super.connect();
52
+ try {
53
+ await client.query("BEGIN");
54
+ await this.applyRlsContext(client, rls);
55
+ const result = await client.query(textOrConfig, values);
56
+ await client.query("COMMIT");
57
+ client.release();
58
+ return result;
59
+ } catch (err) {
60
+ try {
61
+ await client.query("ROLLBACK");
62
+ } catch {
63
+ }
64
+ client.release(err);
65
+ throw err;
66
+ }
67
+ }
68
+ };
69
+
70
+ // src/database/services/primary-database.service.ts
71
+ function _ts_decorate(decorators, target, key, desc3) {
72
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
73
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
74
+ 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;
75
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
76
+ }
77
+ __name(_ts_decorate, "_ts_decorate");
78
+ function _ts_metadata(k, v) {
79
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
80
+ }
81
+ __name(_ts_metadata, "_ts_metadata");
82
+ function _ts_param(paramIndex, decorator) {
83
+ return function(target, key) {
84
+ decorator(target, key, paramIndex);
85
+ };
86
+ }
87
+ __name(_ts_param, "_ts_param");
88
+ var PrimaryDatabaseService = class _PrimaryDatabaseService {
89
+ static {
90
+ __name(this, "PrimaryDatabaseService");
91
+ }
92
+ options;
93
+ logger = new Logger(_PrimaryDatabaseService.name);
94
+ pool = null;
95
+ db = null;
96
+ // Per-request RLS context read by RlsAwarePool per query and by runInTransaction at BEGIN.
97
+ rlsAls = new AsyncLocalStorage();
98
+ // Active Drizzle transaction client so repository queries participate in the transaction.
99
+ txAls = new AsyncLocalStorage();
100
+ constructor(options) {
101
+ this.options = options;
102
+ }
103
+ async onModuleInit() {
104
+ if (this.options.primaryDb) {
105
+ await this.initializeDrizzleClient();
106
+ }
107
+ }
108
+ // Initializes connection to primary database using Drizzle
109
+ async initializeDrizzleClient() {
110
+ try {
111
+ const { host, port = 5432, username, password, database, schema, sslMode = "require" } = this.options.primaryDb;
112
+ this.pool = new RlsAwarePool({
113
+ host,
114
+ port,
115
+ user: username,
116
+ password,
117
+ database,
118
+ max: this.options.maxConnections || 10,
119
+ ssl: sslMode === "disable" ? false : {
120
+ rejectUnauthorized: sslMode !== "no-verify"
121
+ },
122
+ ...schema && {
123
+ options: `-csearch_path=${schema}`
124
+ },
125
+ rlsAls: this.rlsAls,
126
+ txAls: this.txAls,
127
+ applyRlsContext: this.options.applyRlsContext
128
+ });
129
+ this.logger.debug(`Relations keys passed to drizzle: [${Object.keys(this.options.drizzleRelations || {}).join(", ")}]`);
130
+ this.db = drizzle({
131
+ client: this.pool,
132
+ relations: this.options.drizzleRelations
133
+ });
134
+ await this.pool.query("SELECT 1");
135
+ this.logger.log(`Connected to primary database (schema: ${schema ?? "public"})`);
136
+ } catch (error) {
137
+ this.logger.error("Failed to connect to primary database", error);
138
+ throw new InternalServerErrorException("Failed to initialize database connection");
139
+ }
140
+ }
141
+ // Returns the active Drizzle client — the pinned tx inside runInTransaction, else the pool-backed one.
142
+ get drizzleClient() {
143
+ const pinned = this.txAls.getStore();
144
+ if (pinned) return pinned;
145
+ if (!this.db) {
146
+ throw new Error("Primary database client not initialized");
147
+ }
148
+ return this.db;
149
+ }
150
+ // Stashes per-request RLS context in AsyncLocalStorage for downstream queries to apply via SET LOCAL.
151
+ runWithRlsContext(rls, fn) {
152
+ return this.rlsAls.run(rls, fn);
153
+ }
154
+ // Opens a transaction pinning all queries in `fn` to one connection, applying RLS once at BEGIN.
155
+ async runInTransaction(fn) {
156
+ const pinned = this.txAls.getStore();
157
+ if (pinned) {
158
+ return pinned.transaction(async (sp) => this.txAls.run(sp, fn));
159
+ }
160
+ if (!this.db) {
161
+ throw new Error("Primary database client not initialized");
162
+ }
163
+ const rls = this.rlsAls.getStore();
164
+ const applyRls = this.options.applyRlsContext;
165
+ return this.db.transaction(async (tx) => {
166
+ if (rls !== void 0 && applyRls) {
167
+ const sessionClient = tx?.session?.client;
168
+ if (sessionClient) {
169
+ await applyRls(sessionClient, rls);
170
+ }
171
+ }
172
+ return this.txAls.run(tx, fn);
173
+ });
174
+ }
175
+ // Deprecated: prefer runInTransaction. Retained so existing callers keep working until migrated.
176
+ async runWithPinnedConnection(fn) {
177
+ return this.runInTransaction(fn);
178
+ }
179
+ async onModuleDestroy() {
180
+ if (this.pool) {
181
+ await this.pool.end();
182
+ this.logger.log("Disconnected from primary database");
183
+ }
184
+ }
185
+ };
186
+ PrimaryDatabaseService = _ts_decorate([
187
+ Injectable(),
188
+ _ts_param(0, Inject(DATABASE_MODULE_OPTIONS)),
189
+ _ts_metadata("design:type", Function),
190
+ _ts_metadata("design:paramtypes", [
191
+ typeof DatabaseModuleOptions === "undefined" ? Object : DatabaseModuleOptions
192
+ ])
193
+ ], PrimaryDatabaseService);
194
+
195
+ // src/database/database.module.ts
196
+ function _ts_decorate2(decorators, target, key, desc3) {
197
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
198
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
199
+ 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;
200
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
201
+ }
202
+ __name(_ts_decorate2, "_ts_decorate");
203
+ var DatabaseModule = class _DatabaseModule {
204
+ static {
205
+ __name(this, "DatabaseModule");
206
+ }
207
+ // Configures the database module with a single primary connection
208
+ static forServer(options) {
209
+ const asyncProvider = {
210
+ provide: DATABASE_MODULE_OPTIONS,
211
+ useFactory: options.useFactory,
212
+ inject: options.inject || []
213
+ };
214
+ return {
215
+ module: _DatabaseModule,
216
+ providers: [
217
+ {
218
+ provide: Reflector,
219
+ useClass: Reflector
220
+ },
221
+ asyncProvider,
222
+ PrimaryDatabaseService
223
+ ],
224
+ exports: [
225
+ PrimaryDatabaseService,
226
+ asyncProvider
227
+ ]
228
+ };
229
+ }
230
+ };
231
+ DatabaseModule = _ts_decorate2([
232
+ Global(),
233
+ Module({})
234
+ ], DatabaseModule);
235
+
236
+ // src/database/dto/create-response.dto.ts
237
+ import { ApiProperty } from "@nestjs/swagger";
238
+ function _ts_decorate3(decorators, target, key, desc3) {
239
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
240
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
241
+ 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;
242
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
243
+ }
244
+ __name(_ts_decorate3, "_ts_decorate");
245
+ function _ts_metadata2(k, v) {
246
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
247
+ }
248
+ __name(_ts_metadata2, "_ts_metadata");
249
+ var CreateResponseDto = class {
250
+ static {
251
+ __name(this, "CreateResponseDto");
252
+ }
253
+ success;
254
+ message;
255
+ data;
256
+ };
257
+ _ts_decorate3([
258
+ ApiProperty({
259
+ example: true
260
+ }),
261
+ _ts_metadata2("design:type", Boolean)
262
+ ], CreateResponseDto.prototype, "success", void 0);
263
+ _ts_decorate3([
264
+ ApiProperty({
265
+ example: "Resource created successfully"
266
+ }),
267
+ _ts_metadata2("design:type", String)
268
+ ], CreateResponseDto.prototype, "message", void 0);
269
+ _ts_decorate3([
270
+ ApiProperty(),
271
+ _ts_metadata2("design:type", typeof T === "undefined" ? Object : T)
272
+ ], CreateResponseDto.prototype, "data", void 0);
273
+
274
+ // src/database/dto/cursor-list-response.dto.ts
275
+ import { ApiProperty as ApiProperty2, ApiPropertyOptional } from "@nestjs/swagger";
276
+ function _ts_decorate4(decorators, target, key, desc3) {
277
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
278
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
279
+ 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;
280
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
281
+ }
282
+ __name(_ts_decorate4, "_ts_decorate");
283
+ function _ts_metadata3(k, v) {
284
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
285
+ }
286
+ __name(_ts_metadata3, "_ts_metadata");
287
+ var CursorListResponseDto = class {
288
+ static {
289
+ __name(this, "CursorListResponseDto");
290
+ }
291
+ items;
292
+ nextCursor;
293
+ hasMore;
294
+ };
295
+ _ts_decorate4([
296
+ ApiProperty2(),
297
+ _ts_metadata3("design:type", Array)
298
+ ], CursorListResponseDto.prototype, "items", void 0);
299
+ _ts_decorate4([
300
+ ApiPropertyOptional({
301
+ nullable: true
302
+ }),
303
+ _ts_metadata3("design:type", Object)
304
+ ], CursorListResponseDto.prototype, "nextCursor", void 0);
305
+ _ts_decorate4([
306
+ ApiProperty2(),
307
+ _ts_metadata3("design:type", Boolean)
308
+ ], CursorListResponseDto.prototype, "hasMore", void 0);
309
+
310
+ // src/database/dto/import-response.dto.ts
311
+ import { ApiProperty as ApiProperty3, ApiPropertyOptional as ApiPropertyOptional2 } from "@nestjs/swagger";
312
+ function _ts_decorate5(decorators, target, key, desc3) {
313
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
314
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
315
+ 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;
316
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
317
+ }
318
+ __name(_ts_decorate5, "_ts_decorate");
319
+ function _ts_metadata4(k, v) {
320
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
321
+ }
322
+ __name(_ts_metadata4, "_ts_metadata");
323
+ var ValidatedRowDto = class {
324
+ static {
325
+ __name(this, "ValidatedRowDto");
326
+ }
327
+ index;
328
+ data;
329
+ valid;
330
+ errors;
331
+ };
332
+ _ts_decorate5([
333
+ ApiProperty3({
334
+ example: 1
335
+ }),
336
+ _ts_metadata4("design:type", Number)
337
+ ], ValidatedRowDto.prototype, "index", void 0);
338
+ _ts_decorate5([
339
+ ApiProperty3({
340
+ example: {
341
+ code: "products",
342
+ name: "Products"
343
+ }
344
+ }),
345
+ _ts_metadata4("design:type", typeof Record === "undefined" ? Object : Record)
346
+ ], ValidatedRowDto.prototype, "data", void 0);
347
+ _ts_decorate5([
348
+ ApiProperty3({
349
+ example: true
350
+ }),
351
+ _ts_metadata4("design:type", Boolean)
352
+ ], ValidatedRowDto.prototype, "valid", void 0);
353
+ _ts_decorate5([
354
+ ApiProperty3({
355
+ example: [
356
+ "Code already exists"
357
+ ]
358
+ }),
359
+ _ts_metadata4("design:type", Array)
360
+ ], ValidatedRowDto.prototype, "errors", void 0);
361
+ var ImportSummaryDto = class {
362
+ static {
363
+ __name(this, "ImportSummaryDto");
364
+ }
365
+ total;
366
+ valid;
367
+ invalid;
368
+ };
369
+ _ts_decorate5([
370
+ ApiProperty3({
371
+ example: 10
372
+ }),
373
+ _ts_metadata4("design:type", Number)
374
+ ], ImportSummaryDto.prototype, "total", void 0);
375
+ _ts_decorate5([
376
+ ApiProperty3({
377
+ example: 8
378
+ }),
379
+ _ts_metadata4("design:type", Number)
380
+ ], ImportSummaryDto.prototype, "valid", void 0);
381
+ _ts_decorate5([
382
+ ApiProperty3({
383
+ example: 2
384
+ }),
385
+ _ts_metadata4("design:type", Number)
386
+ ], ImportSummaryDto.prototype, "invalid", void 0);
387
+ var ImportResponseDto = class {
388
+ static {
389
+ __name(this, "ImportResponseDto");
390
+ }
391
+ success;
392
+ message;
393
+ created;
394
+ updated;
395
+ skipped;
396
+ rows;
397
+ summary;
398
+ };
399
+ _ts_decorate5([
400
+ ApiProperty3({
401
+ example: true
402
+ }),
403
+ _ts_metadata4("design:type", Boolean)
404
+ ], ImportResponseDto.prototype, "success", void 0);
405
+ _ts_decorate5([
406
+ ApiProperty3({
407
+ example: "Import complete."
408
+ }),
409
+ _ts_metadata4("design:type", String)
410
+ ], ImportResponseDto.prototype, "message", void 0);
411
+ _ts_decorate5([
412
+ ApiPropertyOptional2({
413
+ example: 3
414
+ }),
415
+ _ts_metadata4("design:type", Number)
416
+ ], ImportResponseDto.prototype, "created", void 0);
417
+ _ts_decorate5([
418
+ ApiPropertyOptional2({
419
+ example: 2
420
+ }),
421
+ _ts_metadata4("design:type", Number)
422
+ ], ImportResponseDto.prototype, "updated", void 0);
423
+ _ts_decorate5([
424
+ ApiPropertyOptional2({
425
+ example: 1
426
+ }),
427
+ _ts_metadata4("design:type", Number)
428
+ ], ImportResponseDto.prototype, "skipped", void 0);
429
+ _ts_decorate5([
430
+ ApiPropertyOptional2({
431
+ type: [
432
+ ValidatedRowDto
433
+ ]
434
+ }),
435
+ _ts_metadata4("design:type", Array)
436
+ ], ImportResponseDto.prototype, "rows", void 0);
437
+ _ts_decorate5([
438
+ ApiPropertyOptional2({
439
+ type: ImportSummaryDto
440
+ }),
441
+ _ts_metadata4("design:type", typeof ImportSummaryDto === "undefined" ? Object : ImportSummaryDto)
442
+ ], ImportResponseDto.prototype, "summary", void 0);
443
+
444
+ // src/database/dto/select-options-query.dto.ts
445
+ import { ApiPropertyOptional as ApiPropertyOptional3 } from "@nestjs/swagger";
446
+ import { Type } from "class-transformer";
447
+ import { IsIn, IsInt, IsOptional, IsString, Min } from "class-validator";
448
+ function _ts_decorate6(decorators, target, key, desc3) {
449
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
450
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
451
+ 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;
452
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
453
+ }
454
+ __name(_ts_decorate6, "_ts_decorate");
455
+ function _ts_metadata5(k, v) {
456
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
457
+ }
458
+ __name(_ts_metadata5, "_ts_metadata");
459
+ var SelectOptionsQueryDto = class {
460
+ static {
461
+ __name(this, "SelectOptionsQueryDto");
462
+ }
463
+ search;
464
+ limit;
465
+ offset;
466
+ values;
467
+ excludeIds;
468
+ valueKey;
469
+ labelKey;
470
+ descriptionKey;
471
+ additionalKeys;
472
+ groupIdKey;
473
+ orderByKey;
474
+ orderDirection;
475
+ };
476
+ _ts_decorate6([
477
+ ApiPropertyOptional3({
478
+ description: "Search term to filter by label",
479
+ example: "united"
480
+ }),
481
+ IsOptional(),
482
+ IsString(),
483
+ _ts_metadata5("design:type", String)
484
+ ], SelectOptionsQueryDto.prototype, "search", void 0);
485
+ _ts_decorate6([
486
+ ApiPropertyOptional3({
487
+ description: "Maximum number of results",
488
+ example: 20,
489
+ default: 20
490
+ }),
491
+ IsOptional(),
492
+ Type(() => Number),
493
+ IsInt(),
494
+ Min(1),
495
+ _ts_metadata5("design:type", Number)
496
+ ], SelectOptionsQueryDto.prototype, "limit", void 0);
497
+ _ts_decorate6([
498
+ ApiPropertyOptional3({
499
+ description: "Number of results to skip",
500
+ example: 0,
501
+ default: 0
502
+ }),
503
+ IsOptional(),
504
+ Type(() => Number),
505
+ IsInt(),
506
+ Min(0),
507
+ _ts_metadata5("design:type", Number)
508
+ ], SelectOptionsQueryDto.prototype, "offset", void 0);
509
+ _ts_decorate6([
510
+ ApiPropertyOptional3({
511
+ description: "Comma-separated values to fetch specific options",
512
+ example: "1,2,3"
513
+ }),
514
+ IsOptional(),
515
+ IsString(),
516
+ _ts_metadata5("design:type", String)
517
+ ], SelectOptionsQueryDto.prototype, "values", void 0);
518
+ _ts_decorate6([
519
+ ApiPropertyOptional3({
520
+ description: "Comma-separated IDs to exclude from results (already selected)",
521
+ example: "5,10"
522
+ }),
523
+ IsOptional(),
524
+ IsString(),
525
+ _ts_metadata5("design:type", String)
526
+ ], SelectOptionsQueryDto.prototype, "excludeIds", void 0);
527
+ _ts_decorate6([
528
+ ApiPropertyOptional3({
529
+ description: "Column name for option value",
530
+ example: "id",
531
+ default: "id"
532
+ }),
533
+ IsOptional(),
534
+ IsString(),
535
+ _ts_metadata5("design:type", String)
536
+ ], SelectOptionsQueryDto.prototype, "valueKey", void 0);
537
+ _ts_decorate6([
538
+ ApiPropertyOptional3({
539
+ description: "Column name for option label",
540
+ example: "name",
541
+ default: "name"
542
+ }),
543
+ IsOptional(),
544
+ IsString(),
545
+ _ts_metadata5("design:type", String)
546
+ ], SelectOptionsQueryDto.prototype, "labelKey", void 0);
547
+ _ts_decorate6([
548
+ ApiPropertyOptional3({
549
+ description: "Column name for option description",
550
+ example: "description"
551
+ }),
552
+ IsOptional(),
553
+ IsString(),
554
+ _ts_metadata5("design:type", String)
555
+ ], SelectOptionsQueryDto.prototype, "descriptionKey", void 0);
556
+ _ts_decorate6([
557
+ ApiPropertyOptional3({
558
+ description: "Comma-separated column names to include in option.additionals",
559
+ example: "locationName,availableQuantity"
560
+ }),
561
+ IsOptional(),
562
+ IsString(),
563
+ _ts_metadata5("design:type", String)
564
+ ], SelectOptionsQueryDto.prototype, "additionalKeys", void 0);
565
+ _ts_decorate6([
566
+ ApiPropertyOptional3({
567
+ description: "Column name for group ID",
568
+ example: "regionId"
569
+ }),
570
+ IsOptional(),
571
+ IsString(),
572
+ _ts_metadata5("design:type", String)
573
+ ], SelectOptionsQueryDto.prototype, "groupIdKey", void 0);
574
+ _ts_decorate6([
575
+ ApiPropertyOptional3({
576
+ description: "Column name to sort options by",
577
+ example: "name",
578
+ default: "name"
579
+ }),
580
+ IsOptional(),
581
+ IsString(),
582
+ _ts_metadata5("design:type", String)
583
+ ], SelectOptionsQueryDto.prototype, "orderByKey", void 0);
584
+ _ts_decorate6([
585
+ ApiPropertyOptional3({
586
+ description: "Sort direction for options",
587
+ example: "asc",
588
+ default: "asc",
589
+ enum: [
590
+ "asc",
591
+ "desc"
592
+ ]
593
+ }),
594
+ IsOptional(),
595
+ IsString(),
596
+ IsIn([
597
+ "asc",
598
+ "desc"
599
+ ]),
600
+ _ts_metadata5("design:type", String)
601
+ ], SelectOptionsQueryDto.prototype, "orderDirection", void 0);
602
+
603
+ // src/database/dto/success-response.dto.ts
604
+ import { ApiProperty as ApiProperty4 } from "@nestjs/swagger";
605
+ import { IsBoolean, IsNotEmpty, IsString as IsString2 } from "class-validator";
606
+ function _ts_decorate7(decorators, target, key, desc3) {
607
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
608
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
609
+ 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;
610
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
611
+ }
612
+ __name(_ts_decorate7, "_ts_decorate");
613
+ function _ts_metadata6(k, v) {
614
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
615
+ }
616
+ __name(_ts_metadata6, "_ts_metadata");
617
+ var SuccessResponseDto = class {
618
+ static {
619
+ __name(this, "SuccessResponseDto");
620
+ }
621
+ success;
622
+ message;
623
+ };
624
+ _ts_decorate7([
625
+ ApiProperty4({
626
+ example: true
627
+ }),
628
+ IsNotEmpty(),
629
+ IsBoolean(),
630
+ _ts_metadata6("design:type", Boolean)
631
+ ], SuccessResponseDto.prototype, "success", void 0);
632
+ _ts_decorate7([
633
+ ApiProperty4({
634
+ example: "Operation completed successfully"
635
+ }),
636
+ IsNotEmpty(),
637
+ IsString2(),
638
+ _ts_metadata6("design:type", String)
639
+ ], SuccessResponseDto.prototype, "message", void 0);
640
+
641
+ // src/database/dto/table-response.dto.ts
642
+ import { ApiProperty as ApiProperty5, ApiPropertyOptional as ApiPropertyOptional4 } from "@nestjs/swagger";
643
+ function _ts_decorate8(decorators, target, key, desc3) {
644
+ var c = arguments.length, r = c < 3 ? target : desc3 === null ? desc3 = Object.getOwnPropertyDescriptor(target, key) : desc3, d;
645
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc3);
646
+ 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;
647
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
648
+ }
649
+ __name(_ts_decorate8, "_ts_decorate");
650
+ function _ts_metadata7(k, v) {
651
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
652
+ }
653
+ __name(_ts_metadata7, "_ts_metadata");
654
+ var TableResponseDto = class {
655
+ static {
656
+ __name(this, "TableResponseDto");
657
+ }
658
+ result;
659
+ count;
660
+ state;
661
+ activeViewId;
662
+ };
663
+ _ts_decorate8([
664
+ ApiProperty5(),
665
+ _ts_metadata7("design:type", Array)
666
+ ], TableResponseDto.prototype, "result", void 0);
667
+ _ts_decorate8([
668
+ ApiProperty5(),
669
+ _ts_metadata7("design:type", Number)
670
+ ], TableResponseDto.prototype, "count", void 0);
671
+ _ts_decorate8([
672
+ ApiProperty5(),
673
+ _ts_metadata7("design:type", typeof TableViewState === "undefined" ? Object : TableViewState)
674
+ ], TableResponseDto.prototype, "state", void 0);
675
+ _ts_decorate8([
676
+ ApiPropertyOptional4({
677
+ nullable: true
678
+ }),
679
+ _ts_metadata7("design:type", Object)
680
+ ], TableResponseDto.prototype, "activeViewId", void 0);
681
+
682
+ // src/database/filter/cursor.codec.ts
683
+ import { createHmac, timingSafeEqual } from "crypto";
684
+
685
+ // src/exceptions/bad-gateway.exception.ts
686
+ import { HttpStatus } from "@nestjs/common";
687
+
688
+ // src/exceptions/base-field.exception.ts
689
+ import { HttpException } from "@nestjs/common";
690
+ var HttpProblemException = class extends HttpException {
691
+ static {
692
+ __name(this, "HttpProblemException");
693
+ }
694
+ constructor(detailOrOptions, httpStatus) {
695
+ const options = typeof detailOrOptions === "string" ? {
696
+ detail: detailOrOptions
697
+ } : detailOrOptions;
698
+ super({
699
+ type: options.type ?? "about:blank",
700
+ label: options.label,
701
+ detail: options.detail,
702
+ errors: options.errors ?? []
703
+ }, httpStatus);
704
+ }
705
+ };
706
+
707
+ // src/exceptions/bad-request.exception.ts
708
+ import { HttpStatus as HttpStatus2 } from "@nestjs/common";
709
+ var BadRequestException = class extends HttpProblemException {
710
+ static {
711
+ __name(this, "BadRequestException");
712
+ }
713
+ constructor(detailOrOptions) {
714
+ super(detailOrOptions ?? "Bad Request", HttpStatus2.BAD_REQUEST);
715
+ }
716
+ };
717
+
718
+ // src/exceptions/conflict.exception.ts
719
+ import { HttpStatus as HttpStatus3 } from "@nestjs/common";
720
+
721
+ // src/exceptions/forbidden.exception.ts
722
+ import { HttpStatus as HttpStatus4 } from "@nestjs/common";
723
+
724
+ // src/exceptions/gone.exception.ts
725
+ import { HttpStatus as HttpStatus5 } from "@nestjs/common";
726
+
727
+ // src/exceptions/internal-server-error.exception.ts
728
+ import { HttpStatus as HttpStatus6 } from "@nestjs/common";
729
+
730
+ // src/exceptions/invalid-cursor.exception.ts
731
+ var InvalidCursorException = class extends BadRequestException {
732
+ static {
733
+ __name(this, "InvalidCursorException");
734
+ }
735
+ constructor(detail = "The pagination cursor is invalid.") {
736
+ super({
737
+ label: "Invalid cursor",
738
+ detail
739
+ });
740
+ }
741
+ };
742
+
743
+ // src/exceptions/method-not-allowed.exception.ts
744
+ import { HttpStatus as HttpStatus7 } from "@nestjs/common";
745
+
746
+ // src/exceptions/not-acceptable.exception.ts
747
+ import { HttpStatus as HttpStatus8 } from "@nestjs/common";
748
+
749
+ // src/exceptions/not-found.exception.ts
750
+ import { HttpStatus as HttpStatus9 } from "@nestjs/common";
751
+
752
+ // src/exceptions/not-implemented.exception.ts
753
+ import { HttpStatus as HttpStatus10 } from "@nestjs/common";
754
+
755
+ // src/exceptions/payload-too-large.exception.ts
756
+ import { HttpStatus as HttpStatus11 } from "@nestjs/common";
757
+
758
+ // src/exceptions/request-timeout.exception.ts
759
+ import { HttpStatus as HttpStatus12 } from "@nestjs/common";
760
+
761
+ // src/exceptions/service-unavailable.exception.ts
762
+ import { HttpStatus as HttpStatus13 } from "@nestjs/common";
763
+
764
+ // src/exceptions/too-many-requests.exception.ts
765
+ import { HttpStatus as HttpStatus14 } from "@nestjs/common";
766
+
767
+ // src/exceptions/unauthorized.exception.ts
768
+ import { HttpStatus as HttpStatus15 } from "@nestjs/common";
769
+
770
+ // src/exceptions/unprocessable-entity.exception.ts
771
+ import { HttpStatus as HttpStatus16 } from "@nestjs/common";
772
+
773
+ // src/exceptions/unsupported-media-type.exception.ts
774
+ import { HttpStatus as HttpStatus17 } from "@nestjs/common";
775
+
776
+ // src/exceptions/validation.exception.ts
777
+ import { HttpStatus as HttpStatus18 } from "@nestjs/common";
778
+
779
+ // src/database/filter/cursor.codec.ts
780
+ var CURSOR_SECRET = process.env.KEYSET_CURSOR_SECRET ?? "vritti-dev-insecure-keyset-secret";
781
+ function sign(body) {
782
+ return createHmac("sha256", CURSOR_SECRET).update(body).digest("base64url");
783
+ }
784
+ __name(sign, "sign");
785
+ var CursorCodec = class {
786
+ static {
787
+ __name(this, "CursorCodec");
788
+ }
789
+ // Encodes ORDER BY boundary values into a tamper-evident base64url token bound to the sort signature.
790
+ static encode(values, signature = "") {
791
+ const serialized = values.map((v) => {
792
+ if (v instanceof Date) return {
793
+ __t: "date",
794
+ v: v.toISOString()
795
+ };
796
+ if (v === null || v === void 0) return null;
797
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") return v;
798
+ return String(v);
799
+ });
800
+ const envelope = {
801
+ s: signature,
802
+ v: serialized
803
+ };
804
+ const body = Buffer.from(JSON.stringify(envelope), "utf8").toString("base64url");
805
+ return `${body}.${sign(body)}`;
806
+ }
807
+ // Decodes a cursor back into ordered boundary values, throwing InvalidCursorException on any tamper or sort mismatch.
808
+ static decode(cursor, expectedSignature = "") {
809
+ const dot = cursor.lastIndexOf(".");
810
+ if (dot <= 0) throw new InvalidCursorException("Malformed pagination cursor.");
811
+ const body = cursor.slice(0, dot);
812
+ const mac = cursor.slice(dot + 1);
813
+ const macBuf = Buffer.from(mac, "base64url");
814
+ const expBuf = Buffer.from(sign(body), "base64url");
815
+ if (macBuf.length !== expBuf.length || !timingSafeEqual(macBuf, expBuf)) {
816
+ throw new InvalidCursorException("Pagination cursor failed its integrity check.");
817
+ }
818
+ let envelope;
819
+ try {
820
+ envelope = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
821
+ } catch {
822
+ throw new InvalidCursorException("Pagination cursor could not be parsed.");
823
+ }
824
+ if (!envelope || typeof envelope.s !== "string" || !Array.isArray(envelope.v)) {
825
+ throw new InvalidCursorException("Pagination cursor has an unexpected shape.");
826
+ }
827
+ if (envelope.s !== expectedSignature) {
828
+ throw new InvalidCursorException("Pagination cursor does not match the current sort order.");
829
+ }
830
+ return envelope.v.map((v) => {
831
+ if (v && typeof v === "object" && "__t" in v && v.__t === "date") return new Date(v.v);
832
+ return v;
833
+ });
834
+ }
835
+ };
836
+
837
+ // src/database/filter/filter.processor.ts
838
+ import { and, asc, desc, eq, gt, gte, ilike, inArray, lt, lte, ne, notIlike, notInArray, or } from "drizzle-orm";
839
+ var FilterProcessor = class {
840
+ static {
841
+ __name(this, "FilterProcessor");
842
+ }
843
+ // Returns undefined if no conditions (Drizzle accepts undefined as "no WHERE")
844
+ static buildWhere(filters = [], fieldMap) {
845
+ const conditions = filters.flatMap((f) => {
846
+ const def = fieldMap[f.field];
847
+ if (!def) return [];
848
+ if ("expression" in def) return Array.isArray(f.value) ? [] : [
849
+ def.expression(f.value, f.operator)
850
+ ];
851
+ const { column: col } = def;
852
+ const val = f.value;
853
+ switch (f.operator) {
854
+ case "equals":
855
+ if (def.type === "boolean") return [
856
+ eq(col, val === "true" || val === 1)
857
+ ];
858
+ return [
859
+ eq(col, val)
860
+ ];
861
+ case "notEquals":
862
+ if (def.type === "boolean") return [
863
+ ne(col, val === "true" || val === 1)
864
+ ];
865
+ return [
866
+ ne(col, val)
867
+ ];
868
+ case "contains":
869
+ return [
870
+ ilike(col, `%${val}%`)
871
+ ];
872
+ case "notContains":
873
+ return [
874
+ notIlike(col, `%${val}%`)
875
+ ];
876
+ case "gt":
877
+ return [
878
+ gt(col, val)
879
+ ];
880
+ case "gte":
881
+ return [
882
+ gte(col, val)
883
+ ];
884
+ case "lt":
885
+ return [
886
+ lt(col, val)
887
+ ];
888
+ case "lte":
889
+ return [
890
+ lte(col, val)
891
+ ];
892
+ case "isAnyOf":
893
+ return [
894
+ inArray(col, Array.isArray(val) ? val : [
895
+ String(val)
896
+ ])
897
+ ];
898
+ case "isNotAnyOf":
899
+ return [
900
+ notInArray(col, Array.isArray(val) ? val : [
901
+ String(val)
902
+ ])
903
+ ];
904
+ default:
905
+ return [];
906
+ }
907
+ });
908
+ return conditions.length ? and(...conditions) : void 0;
909
+ }
910
+ // Builds a search WHERE — OR across all string fields when columnId is 'all', otherwise a single ilike
911
+ static buildSearch(search, fieldMap) {
912
+ if (!search?.value) return void 0;
913
+ if (search.columnId === "all") {
914
+ const conditions = Object.values(fieldMap).filter((def2) => "column" in def2 && def2.type === "string").map((def2) => ilike(def2.column, `%${search.value}%`));
915
+ return conditions.length ? or(...conditions) : void 0;
916
+ }
917
+ const def = fieldMap[search.columnId];
918
+ if (!def || !("column" in def)) return void 0;
919
+ return ilike(def.column, `%${search.value}%`);
920
+ }
921
+ // Maps each SortCondition to an asc/desc SQL expression
922
+ static buildOrderBy(sort = [], fieldMap) {
923
+ return sort.flatMap((s) => {
924
+ const def = fieldMap[s.field];
925
+ if (!def || !("column" in def)) return [];
926
+ return [
927
+ s.direction === "asc" ? asc(def.column) : desc(def.column)
928
+ ];
929
+ });
930
+ }
931
+ };
932
+
933
+ // src/database/filter/filter.types.ts
934
+ var FilterOperators = {
935
+ EQUALS: "equals",
936
+ NOT_EQUALS: "notEquals",
937
+ CONTAINS: "contains",
938
+ NOT_CONTAINS: "notContains",
939
+ GT: "gt",
940
+ GTE: "gte",
941
+ LT: "lt",
942
+ LTE: "lte",
943
+ IS_ANY_OF: "isAnyOf",
944
+ IS_NOT_ANY_OF: "isNotAnyOf"
945
+ };
946
+
947
+ // src/database/filter/keyset.processor.ts
948
+ import { and as and2, eq as eq2, gt as gt2, isNotNull, isNull, lt as lt2, or as or2, sql } from "drizzle-orm";
949
+ var MAX_PAGE_SIZE = 100;
950
+ function keysetSignature(entries) {
951
+ return entries.map((e) => `${e.key}:${e.direction}`).join(",");
952
+ }
953
+ __name(keysetSignature, "keysetSignature");
954
+ var KeysetProcessor = class _KeysetProcessor {
955
+ static {
956
+ __name(this, "KeysetProcessor");
957
+ }
958
+ // Builds the "after this row" predicate for keyset pagination.
959
+ static buildAfter(orderBy, values) {
960
+ const first = orderBy[0];
961
+ if (!first) return sql`true`;
962
+ const uniform = orderBy.every((o) => o.direction === first.direction);
963
+ const anyNullable = orderBy.some((o) => o.nulls !== void 0);
964
+ if (uniform && !anyNullable && orderBy.length >= 2) {
965
+ return _KeysetProcessor.buildRowValue(orderBy, values, first.direction);
966
+ }
967
+ return _KeysetProcessor.buildOrExpansion(orderBy, values);
968
+ }
969
+ // (c1, c2, …) > (v1, v2, …) for asc, < for desc. Correct only for uniform direction, no NULLs.
970
+ static buildRowValue(orderBy, values, direction) {
971
+ const cols = sql.join(orderBy.map((o) => sql`${o.column}`), sql`, `);
972
+ const vals = sql.join(values.map((v) => sql`${v}`), sql`, `);
973
+ const op = direction === "asc" ? sql`>` : sql`<`;
974
+ return sql`(${cols}) ${op} (${vals})`;
975
+ }
976
+ // Lexicographic OR-expansion, NULL-aware per column when a `nulls` placement is declared.
977
+ static buildOrExpansion(orderBy, values) {
978
+ const groups = [];
979
+ for (let i = 0; i < orderBy.length; i++) {
980
+ const current = orderBy[i];
981
+ if (!current) continue;
982
+ const conditions = [];
983
+ for (let j = 0; j < i; j++) {
984
+ const prior = orderBy[j];
985
+ if (prior) conditions.push(_KeysetProcessor.tie(prior.column, values[j]));
986
+ }
987
+ conditions.push(_KeysetProcessor.strictlyAfter(current, values[i]));
988
+ const group = conditions.length === 1 ? conditions[0] : and2(...conditions);
989
+ if (group) groups.push(group);
990
+ }
991
+ const firstGroup = groups[0];
992
+ if (groups.length === 1 && firstGroup) return firstGroup;
993
+ return or2(...groups);
994
+ }
995
+ // Tie on an earlier column: match its boundary value (NULL-safe).
996
+ static tie(column, value) {
997
+ return value === null || value === void 0 ? isNull(column) : eq2(column, value);
998
+ }
999
+ // Strictly past the boundary on this column, respecting direction and NULL placement.
1000
+ static strictlyAfter(o, value) {
1001
+ if (o.nulls === void 0) {
1002
+ return o.direction === "asc" ? gt2(o.column, value) : lt2(o.column, value);
1003
+ }
1004
+ const nullsLast = o.nulls === "last";
1005
+ if (value === null || value === void 0) {
1006
+ return nullsLast ? sql`false` : isNotNull(o.column);
1007
+ }
1008
+ const cmp = o.direction === "asc" ? gt2(o.column, value) : lt2(o.column, value);
1009
+ return nullsLast ? or2(cmp, isNull(o.column)) : cmp;
1010
+ }
1011
+ };
1012
+
1013
+ // src/database/repositories/primary-base.repository.ts
1014
+ import { Logger as Logger2 } from "@nestjs/common";
1015
+ import { and as and3, asc as asc2, desc as desc2, eq as eq3, getTableName, getViewName, ilike as ilike2, inArray as inArray2, is, notInArray as notInArray2, sql as sql2 } from "drizzle-orm";
1016
+ import { PgViewBase } from "drizzle-orm/pg-core/view-base";
1017
+ function snakeToCamel(str) {
1018
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
1019
+ }
1020
+ __name(snakeToCamel, "snakeToCamel");
1021
+ var PrimaryBaseRepository = class {
1022
+ static {
1023
+ __name(this, "PrimaryBaseRepository");
1024
+ }
1025
+ database;
1026
+ table;
1027
+ logger;
1028
+ sequence;
1029
+ tableName;
1030
+ isView;
1031
+ get db() {
1032
+ return this.database.drizzleClient;
1033
+ }
1034
+ get model() {
1035
+ if (this.isView) {
1036
+ throw new Error(`${this.constructor.name}: relational queries (.model) are not supported on the view '${this.tableName}'. Use findForSelect / findAllAndCount instead.`);
1037
+ }
1038
+ const query = this.database.drizzleClient.query;
1039
+ const queryKeys = Object.keys(query || {});
1040
+ this.logger.debug(`Looking for '${this.tableName}' in query keys: [${queryKeys.join(", ")}]`);
1041
+ const model = query[this.tableName];
1042
+ if (!model) {
1043
+ this.logger.error(`Table '${this.tableName}' not found in query object. Available: [${queryKeys.join(", ")}]`);
1044
+ }
1045
+ return model;
1046
+ }
1047
+ constructor(database, table, options) {
1048
+ this.database = database;
1049
+ this.table = table;
1050
+ this.isView = is(table, PgViewBase);
1051
+ const dbTableName = this.isView ? getViewName(table) : getTableName(table);
1052
+ this.tableName = snakeToCamel(dbTableName);
1053
+ this.sequence = options?.sequence;
1054
+ this.logger = new Logger2(this.constructor.name);
1055
+ this.logger.debug(`Initialized ${this.constructor.name}`);
1056
+ this.logger.debug(`Table name: '${dbTableName}' -> query key: '${this.tableName}'`);
1057
+ }
1058
+ // Returns next value from configured sequence, or an explicitly passed sequence
1059
+ async nextSequenceValue(sequence) {
1060
+ const resolvedSequence = sequence ?? this.sequence;
1061
+ if (!resolvedSequence) {
1062
+ throw new Error(`${this.constructor.name}: sequence is required for nextSequenceValue`);
1063
+ }
1064
+ const sequenceName = resolvedSequence.schema ? `${resolvedSequence.schema}.${resolvedSequence.seqName}` : resolvedSequence.seqName;
1065
+ const result = await this.db.execute(sql2`select nextval(${sequenceName}::regclass) as sequence_value`);
1066
+ const rows = result.rows ?? [];
1067
+ return Number(rows[0]?.sequence_value ?? 1);
1068
+ }
1069
+ // Creates a new record and returns it
1070
+ async create(data, tx) {
1071
+ this.logger.log("Creating record");
1072
+ const db = tx ?? this.db;
1073
+ const results = await db.insert(this.table).values(data).returning();
1074
+ const record = results[0];
1075
+ if (!record) throw new Error(`${this.tableName}: database operation returned no record`);
1076
+ return record;
1077
+ }
1078
+ // Finds a single record by primary key ID
1079
+ async findById(id) {
1080
+ this.logger.debug(`Finding record by ID: ${id}`);
1081
+ return this.model.findFirst({
1082
+ where: {
1083
+ id
1084
+ }
1085
+ });
1086
+ }
1087
+ // Finds a single record matching the given where filter
1088
+ async findOne(where) {
1089
+ this.logger.debug("Finding record with custom query");
1090
+ return this.model.findFirst({
1091
+ where
1092
+ });
1093
+ }
1094
+ // Finds multiple records with optional filtering, ordering, and pagination
1095
+ async findMany(options) {
1096
+ this.logger.debug("Finding multiple records");
1097
+ return this.model.findMany(options);
1098
+ }
1099
+ // Builds a select query with optional custom fields, joins, filter, grouping, ordering, and pagination
1100
+ buildSelectQuery(options) {
1101
+ let query = (options?.select ? this.db.select(options.select).from(this.table) : this.db.select().from(this.table)).$dynamic();
1102
+ if (options?.leftJoin) {
1103
+ query = query.leftJoin(options.leftJoin.table, options.leftJoin.on);
1104
+ }
1105
+ if (options?.leftJoins) {
1106
+ for (const join of options.leftJoins) {
1107
+ query = query.leftJoin(join.table, join.on);
1108
+ }
1109
+ }
1110
+ if (options?.where) {
1111
+ query = query.where(options.where);
1112
+ }
1113
+ if (options?.groupBy?.length) {
1114
+ query = query.groupBy(...options.groupBy);
1115
+ }
1116
+ if (options?.orderBy?.length) {
1117
+ query = query.orderBy(...options.orderBy);
1118
+ }
1119
+ if (options?.limit) {
1120
+ query = query.limit(options.limit);
1121
+ }
1122
+ if (options?.offset) {
1123
+ query = query.offset(options.offset);
1124
+ }
1125
+ return query;
1126
+ }
1127
+ // Returns paginated result and total count, with optional custom select, LEFT JOINs, GROUP BY, and ordering
1128
+ async findAllAndCount(options) {
1129
+ let countResultPromise;
1130
+ if (options?.groupBy?.length) {
1131
+ let subq = this.db.select({
1132
+ _: sql2`1`
1133
+ }).from(this.table).$dynamic();
1134
+ if (options.leftJoin) {
1135
+ subq = subq.leftJoin(options.leftJoin.table, options.leftJoin.on);
1136
+ }
1137
+ if (options.leftJoins) {
1138
+ for (const join of options.leftJoins) {
1139
+ subq = subq.leftJoin(join.table, join.on);
1140
+ }
1141
+ }
1142
+ if (options.where) {
1143
+ subq = subq.where(options.where);
1144
+ }
1145
+ subq = subq.groupBy(...options.groupBy);
1146
+ const named = subq.as("_count_subq");
1147
+ countResultPromise = this.db.select({
1148
+ count: sql2`count(*)::int`
1149
+ }).from(named);
1150
+ } else {
1151
+ let countQuery = this.db.select({
1152
+ count: sql2`count(*)::int`
1153
+ }).from(this.table).$dynamic();
1154
+ if (options?.leftJoin) {
1155
+ countQuery = countQuery.leftJoin(options.leftJoin.table, options.leftJoin.on);
1156
+ }
1157
+ if (options?.leftJoins) {
1158
+ for (const join of options.leftJoins) {
1159
+ countQuery = countQuery.leftJoin(join.table, join.on);
1160
+ }
1161
+ }
1162
+ if (options?.where) {
1163
+ countQuery = countQuery.where(options.where);
1164
+ }
1165
+ countResultPromise = countQuery;
1166
+ }
1167
+ const [countResult, result] = await Promise.all([
1168
+ countResultPromise,
1169
+ this.buildSelectQuery(options)
1170
+ ]);
1171
+ return {
1172
+ result,
1173
+ count: countResult[0].count
1174
+ };
1175
+ }
1176
+ // Fetches limit+1 rows for keyset pagination and trims, returning rows plus hasMore.
1177
+ async findKeyset(options) {
1178
+ const limit = Math.min(Math.max(1, Math.trunc(options.limit) || 1), MAX_PAGE_SIZE);
1179
+ const rows = await this.buildSelectQuery({
1180
+ ...options,
1181
+ limit: limit + 1
1182
+ });
1183
+ const hasMore = rows.length > limit;
1184
+ return {
1185
+ rows: hasMore ? rows.slice(0, limit) : rows,
1186
+ hasMore
1187
+ };
1188
+ }
1189
+ // Updates a record by ID and returns the updated record
1190
+ async update(id, data, tx) {
1191
+ this.logger.log(`Updating record with ID: ${id}`);
1192
+ const db = tx ?? this.db;
1193
+ const idColumn = this.table.id;
1194
+ if (!idColumn) throw new Error(`Table '${this.tableName}' has no 'id' column`);
1195
+ const results = await db.update(this.table).set(data).where(eq3(idColumn, id)).returning();
1196
+ const record = results[0];
1197
+ if (!record) throw new Error(`${this.tableName}: database operation returned no record`);
1198
+ return record;
1199
+ }
1200
+ // Updates all records matching the SQL condition and returns the affected count
1201
+ async updateMany(where, data, tx) {
1202
+ this.logger.log("Updating multiple records");
1203
+ const db = tx ?? this.db;
1204
+ const result = await db.update(this.table).set(data).where(where);
1205
+ return {
1206
+ count: result.rowCount ?? 0
1207
+ };
1208
+ }
1209
+ // Deletes a record by ID and returns the deleted record
1210
+ async delete(id, tx) {
1211
+ this.logger.log(`Deleting record with ID: ${id}`);
1212
+ const db = tx ?? this.db;
1213
+ const idColumn = this.table.id;
1214
+ if (!idColumn) throw new Error(`Table '${this.tableName}' has no 'id' column`);
1215
+ const results = await db.delete(this.table).where(eq3(idColumn, id)).returning();
1216
+ const record = results[0];
1217
+ if (!record) throw new Error(`${this.tableName}: database operation returned no record`);
1218
+ return record;
1219
+ }
1220
+ // Deletes all records matching the SQL condition and returns the affected count
1221
+ async deleteMany(where, tx) {
1222
+ this.logger.log("Deleting multiple records");
1223
+ const db = tx ?? this.db;
1224
+ const result = await db.delete(this.table).where(where);
1225
+ return {
1226
+ count: result.rowCount ?? 0
1227
+ };
1228
+ }
1229
+ // Counts records matching the optional SQL condition
1230
+ async count(where) {
1231
+ this.logger.debug("Counting records");
1232
+ let query = this.db.select({
1233
+ count: sql2`count(*)::int`
1234
+ }).from(this.table).$dynamic();
1235
+ if (where) {
1236
+ query = query.where(where);
1237
+ }
1238
+ const results = await query;
1239
+ return results[0].count;
1240
+ }
1241
+ // Returns true if at least one record matches the SQL condition
1242
+ async exists(where) {
1243
+ const count = await this.count(where);
1244
+ return count > 0;
1245
+ }
1246
+ // Executes the callback within a database transaction, applying the ALS RLS context once at BEGIN.
1247
+ async transaction(callback) {
1248
+ return this.database.runInTransaction(async () => callback(this.database.drizzleClient));
1249
+ }
1250
+ // Finds records formatted as select dropdown options with optional search, pagination, and grouping
1251
+ async findForSelect(config) {
1252
+ this.logger.debug("Finding records for select dropdown");
1253
+ const selectFn = config.distinct ? this.db.selectDistinct.bind(this.db) : this.db.select.bind(this.db);
1254
+ const parsedValues = typeof config.values === "string" ? config.values.split(",").map((v) => v.trim()).filter(Boolean) : config.values;
1255
+ const parsedExcludeIds = typeof config.excludeIds === "string" ? config.excludeIds.split(",").map((v) => v.trim()).filter(Boolean) : config.excludeIds ?? [];
1256
+ const tableColumns = this.table;
1257
+ const joinTables = config.joins?.map((join) => join.table) ?? [];
1258
+ const resolveColumn = /* @__PURE__ */ __name((key) => {
1259
+ if (tableColumns[key]) return tableColumns[key];
1260
+ for (const joinColumns of joinTables) {
1261
+ if (joinColumns[key]) return joinColumns[key];
1262
+ }
1263
+ return void 0;
1264
+ }, "resolveColumn");
1265
+ const valueCol = resolveColumn(config.value);
1266
+ if (!valueCol) throw new Error(`Column '${config.value}' not found in table '${this.tableName}' or its joins`);
1267
+ const labelCol = resolveColumn(config.label);
1268
+ if (!labelCol) throw new Error(`Column '${config.label}' not found in table '${this.tableName}' or its joins`);
1269
+ const descriptionCol = config.description ? resolveColumn(config.description) : void 0;
1270
+ const parseKeys = /* @__PURE__ */ __name((input) => {
1271
+ if (!input) return [];
1272
+ const values = Array.isArray(input) ? input : input.split(",");
1273
+ return values.map((v) => v.trim()).filter(Boolean);
1274
+ }, "parseKeys");
1275
+ const additionalKeys = parseKeys(config.additionalKeys);
1276
+ const additionalEntries = [
1277
+ ...additionalKeys.map((key) => ({
1278
+ key,
1279
+ expr: resolveColumn(key)
1280
+ })).filter((e) => Boolean(e.expr)),
1281
+ ...Object.entries(config.additionalExpressions ?? {}).map(([key, expr]) => ({
1282
+ key,
1283
+ expr
1284
+ }))
1285
+ ];
1286
+ const additionalAlias = /* @__PURE__ */ __name((key) => `__additional_${key}`, "additionalAlias");
1287
+ if (parsedValues && parsedValues.length > 0) {
1288
+ const selectCols = {
1289
+ value: valueCol,
1290
+ label: labelCol
1291
+ };
1292
+ if (descriptionCol) selectCols.description = descriptionCol;
1293
+ if (config.groupIdKey) {
1294
+ const groupIdCol = resolveColumn(config.groupIdKey);
1295
+ if (groupIdCol) selectCols.groupId = groupIdCol;
1296
+ }
1297
+ for (const entry of additionalEntries) {
1298
+ selectCols[additionalAlias(entry.key)] = entry.expr;
1299
+ }
1300
+ let valuesQuery = selectFn(selectCols).from(this.table).$dynamic();
1301
+ if (config.joins) {
1302
+ for (const join of config.joins) {
1303
+ if (join.type === "inner") {
1304
+ valuesQuery = valuesQuery.innerJoin(join.table, join.on);
1305
+ } else {
1306
+ valuesQuery = valuesQuery.leftJoin(join.table, join.on);
1307
+ }
1308
+ }
1309
+ }
1310
+ const rows2 = await valuesQuery.where(inArray2(valueCol, parsedValues));
1311
+ return {
1312
+ options: rows2.map((row) => ({
1313
+ value: row.value,
1314
+ label: String(row.label),
1315
+ ...descriptionCol && row.description != null ? {
1316
+ description: String(row.description)
1317
+ } : {},
1318
+ ...config.groupIdKey && row.groupId != null ? {
1319
+ groupId: row.groupId
1320
+ } : {},
1321
+ ...additionalEntries.length > 0 ? {
1322
+ additionals: additionalEntries.reduce((acc, entry) => {
1323
+ const value = row[additionalAlias(entry.key)];
1324
+ if (value !== void 0) {
1325
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
1326
+ acc[entry.key] = value;
1327
+ } else {
1328
+ acc[entry.key] = String(value);
1329
+ }
1330
+ }
1331
+ return acc;
1332
+ }, {})
1333
+ } : {}
1334
+ })),
1335
+ hasMore: false,
1336
+ ...config.groups ? {
1337
+ groups: config.groups
1338
+ } : {}
1339
+ };
1340
+ }
1341
+ const selectFields = {
1342
+ value: valueCol,
1343
+ label: labelCol,
1344
+ totalCount: sql2`count(*) over()`.mapWith(Number)
1345
+ };
1346
+ if (descriptionCol) selectFields.description = descriptionCol;
1347
+ if (config.groupIdKey) {
1348
+ const groupIdCol = resolveColumn(config.groupIdKey);
1349
+ if (groupIdCol) selectFields.groupId = groupIdCol;
1350
+ }
1351
+ for (const entry of additionalEntries) {
1352
+ selectFields[additionalAlias(entry.key)] = entry.expr;
1353
+ }
1354
+ const conditions = [];
1355
+ if (config.search) {
1356
+ conditions.push(ilike2(labelCol, `%${config.search}%`));
1357
+ }
1358
+ if (parsedExcludeIds.length > 0) {
1359
+ conditions.push(notInArray2(valueCol, parsedExcludeIds));
1360
+ }
1361
+ if (config.where) {
1362
+ for (const [field, val] of Object.entries(config.where)) {
1363
+ const column = tableColumns[field];
1364
+ if (column) {
1365
+ conditions.push(eq3(column, val));
1366
+ }
1367
+ }
1368
+ }
1369
+ if (config.conditions) {
1370
+ conditions.push(...config.conditions);
1371
+ }
1372
+ const orderByKey = config.orderByKey || (config.orderBy ? Object.keys(config.orderBy)[0] : void 0);
1373
+ const orderDirection = config.orderDirection || (config.orderBy ? Object.values(config.orderBy)[0] : void 0);
1374
+ const orderByCol = orderByKey ? tableColumns[orderByKey] ?? labelCol : labelCol;
1375
+ const limit = Number(config.limit) || 20;
1376
+ const offset = Number(config.offset) || 0;
1377
+ let query = selectFn(selectFields).from(this.table).$dynamic();
1378
+ if (config.joins) {
1379
+ for (const join of config.joins) {
1380
+ if (join.type === "inner") {
1381
+ query = query.innerJoin(join.table, join.on);
1382
+ } else {
1383
+ query = query.leftJoin(join.table, join.on);
1384
+ }
1385
+ }
1386
+ }
1387
+ if (conditions.length > 0) {
1388
+ query = query.where(conditions.length === 1 ? conditions[0] : and3(...conditions));
1389
+ }
1390
+ const orderClauses = [];
1391
+ if (config.groupIdKey) {
1392
+ const groupIdCol = resolveColumn(config.groupIdKey);
1393
+ if (groupIdCol) orderClauses.push(asc2(groupIdCol));
1394
+ }
1395
+ orderClauses.push(orderDirection === "desc" ? desc2(orderByCol) : asc2(orderByCol));
1396
+ query = query.orderBy(...orderClauses).limit(limit).offset(offset);
1397
+ const rows = await query;
1398
+ const totalCount = rows.length > 0 ? rows[0].totalCount : 0;
1399
+ const options = rows.map((row) => ({
1400
+ value: row.value,
1401
+ label: String(row.label),
1402
+ ...descriptionCol && row.description != null ? {
1403
+ description: String(row.description)
1404
+ } : {},
1405
+ ...config.groupIdKey && row.groupId != null ? {
1406
+ groupId: row.groupId
1407
+ } : {},
1408
+ ...additionalEntries.length > 0 ? {
1409
+ additionals: additionalEntries.reduce((acc, entry) => {
1410
+ const value = row[additionalAlias(entry.key)];
1411
+ if (value !== void 0) {
1412
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
1413
+ acc[entry.key] = value;
1414
+ } else {
1415
+ acc[entry.key] = String(value);
1416
+ }
1417
+ }
1418
+ return acc;
1419
+ }, {})
1420
+ } : {}
1421
+ }));
1422
+ let resolvedGroups = config.groups;
1423
+ if (config.groupTable && config.groupIdKey) {
1424
+ const groupTableColumns = config.groupTable;
1425
+ const groupIdKey = config.groupTableIdKey ?? "id";
1426
+ const groupNameKey = config.groupLabelKey ?? "name";
1427
+ const groupIdCol = groupTableColumns[groupIdKey];
1428
+ if (!groupIdCol) throw new Error(`Column '${groupIdKey}' not found in group table`);
1429
+ const groupNameCol = groupTableColumns[groupNameKey];
1430
+ if (!groupNameCol) throw new Error(`Column '${groupNameKey}' not found in group table`);
1431
+ const groupRows = await this.db.select({
1432
+ id: groupIdCol,
1433
+ name: groupNameCol
1434
+ }).from(config.groupTable).orderBy(asc2(groupNameCol));
1435
+ resolvedGroups = groupRows.map((r) => ({
1436
+ id: r.id,
1437
+ name: String(r.name)
1438
+ }));
1439
+ }
1440
+ return {
1441
+ options,
1442
+ hasMore: offset + limit < totalCount,
1443
+ totalCount,
1444
+ ...resolvedGroups ? {
1445
+ groups: resolvedGroups
1446
+ } : {}
1447
+ };
1448
+ }
1449
+ };
1450
+ export {
1451
+ CreateResponseDto,
1452
+ CursorCodec,
1453
+ CursorListResponseDto,
1454
+ DatabaseModule,
1455
+ FilterOperators,
1456
+ FilterProcessor,
1457
+ ImportResponseDto,
1458
+ ImportSummaryDto,
1459
+ KeysetProcessor,
1460
+ MAX_PAGE_SIZE,
1461
+ PrimaryBaseRepository,
1462
+ PrimaryDatabaseService,
1463
+ SelectOptionsQueryDto,
1464
+ SuccessResponseDto,
1465
+ TableResponseDto,
1466
+ ValidatedRowDto,
1467
+ keysetSignature
1468
+ };
1469
+ //# sourceMappingURL=database.js.map