@flusys/nestjs-shared 5.1.1 → 5.1.3

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 (31) hide show
  1. package/cjs/classes/api-controller.class.js +16 -10
  2. package/cjs/classes/api-service.class.js +67 -35
  3. package/cjs/classes/index.js +0 -1
  4. package/cjs/dtos/identity-response.dto.js +4 -8
  5. package/cjs/entities/identity.js +8 -2
  6. package/cjs/modules/datasource/index.js +0 -1
  7. package/cjs/modules/datasource/multi-tenant-datasource.service.js +24 -85
  8. package/classes/api-controller.class.d.ts +1 -0
  9. package/classes/api-service.class.d.ts +13 -6
  10. package/classes/index.d.ts +0 -1
  11. package/decorators/current-user.decorator.d.ts +1 -1
  12. package/fesm/classes/api-controller.class.js +16 -10
  13. package/fesm/classes/api-service.class.js +70 -38
  14. package/fesm/classes/index.js +0 -1
  15. package/fesm/dtos/identity-response.dto.js +4 -8
  16. package/fesm/entities/identity.js +8 -2
  17. package/fesm/interfaces/datasource.interface.js +1 -20
  18. package/fesm/modules/datasource/index.js +0 -1
  19. package/fesm/modules/datasource/multi-tenant-datasource.service.js +24 -85
  20. package/guards/permission.guard.d.ts +1 -1
  21. package/interceptors/idempotency.interceptor.d.ts +1 -1
  22. package/interfaces/notification-adapter.interface.d.ts +13 -14
  23. package/modules/datasource/index.d.ts +0 -1
  24. package/modules/datasource/multi-tenant-datasource.service.d.ts +4 -13
  25. package/package.json +15 -15
  26. package/cjs/classes/request-scoped-api.service.js +0 -61
  27. package/cjs/modules/datasource/datasource.module.js +0 -117
  28. package/classes/request-scoped-api.service.d.ts +0 -14
  29. package/fesm/classes/request-scoped-api.service.js +0 -51
  30. package/fesm/modules/datasource/datasource.module.js +0 -107
  31. package/modules/datasource/datasource.module.d.ts +0 -19
@@ -11,11 +11,11 @@ Object.defineProperty(exports, "createApiController", {
11
11
  const _common = require("@nestjs/common");
12
12
  const _swagger = require("@nestjs/swagger");
13
13
  const _classtransformer = require("class-transformer");
14
+ const _messagekeys = require("../constants/message-keys");
14
15
  const _decorators = require("../decorators");
15
16
  const _apiresponsedecorator = require("../decorators/api-response.decorator");
16
17
  const _dtos = require("../dtos");
17
18
  const _exceptions = require("../exceptions");
18
- const _messagekeys = require("../constants/message-keys");
19
19
  const _guards = require("../guards");
20
20
  const _interceptors = require("../interceptors");
21
21
  function _define_property(obj, key, value) {
@@ -108,6 +108,12 @@ function _ts_param(paramIndex, decorator) {
108
108
  return (0, _common.applyDecorators)(...decorators);
109
109
  }
110
110
  function createApiController(createDtoClass, updateDtoClass, responseDtoClass, options = {}) {
111
+ const excludeExtraneousValues = options.excludeExtraneousValues ?? true;
112
+ function toDto(cls, input) {
113
+ return (0, _classtransformer.plainToInstance)(cls, input, {
114
+ excludeExtraneousValues
115
+ });
116
+ }
111
117
  // Entity name for message keys (defaults to 'item')
112
118
  const entityName = options.entityName ?? 'item';
113
119
  // Determine if security is global (applies to all) or per-endpoint
@@ -163,7 +169,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
163
169
  });
164
170
  }
165
171
  const entity = await this.service.insert(addDto, user);
166
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entity);
172
+ const data = toDto(responseDtoClass, entity);
167
173
  return {
168
174
  success: true,
169
175
  message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)} created successfully`,
@@ -183,7 +189,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
183
189
  });
184
190
  }
185
191
  const entities = await this.service.insertMany(addDto, user);
186
- const data = entities.map((item)=>(0, _classtransformer.plainToInstance)(responseDtoClass, item));
192
+ const data = entities.map((item)=>toDto(responseDtoClass, item));
187
193
  return {
188
194
  success: true,
189
195
  message: `${data.length} ${entityName}s created successfully`,
@@ -211,7 +217,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
211
217
  });
212
218
  }
213
219
  const entity = await this.service.findById(id, user, body?.select);
214
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entity);
220
+ const data = toDto(responseDtoClass, entity);
215
221
  return {
216
222
  success: true,
217
223
  message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)} retrieved successfully`,
@@ -231,7 +237,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
231
237
  });
232
238
  }
233
239
  const entities = await this.service.findByIds(body.ids, user, body?.select);
234
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entities);
240
+ const data = entities.map((item)=>toDto(responseDtoClass, item));
235
241
  return {
236
242
  success: true,
237
243
  message: `${data.length} ${entityName}${data.length !== 1 ? 's' : ''} retrieved successfully`,
@@ -258,7 +264,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
258
264
  });
259
265
  }
260
266
  const entity = await this.service.update(updateDto, user);
261
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entity);
267
+ const data = toDto(responseDtoClass, entity);
262
268
  return {
263
269
  success: true,
264
270
  message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)} updated successfully`,
@@ -278,7 +284,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
278
284
  });
279
285
  }
280
286
  const entities = await this.service.updateMany(updateDtos, user);
281
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entities);
287
+ const data = entities.map((item)=>toDto(responseDtoClass, item));
282
288
  return {
283
289
  success: true,
284
290
  message: `${data.length} ${entityName}s updated successfully`,
@@ -315,7 +321,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
315
321
  }
316
322
  }
317
323
  const allEntities = await this.service.bulkUpsert(toInsert, toUpdate, user);
318
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, allEntities);
324
+ const data = allEntities.map((item)=>toDto(responseDtoClass, item));
319
325
  return {
320
326
  success: true,
321
327
  message: `${data.length} ${entityName}s upserted successfully`,
@@ -353,7 +359,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
353
359
  throw new _exceptions.NotFoundException(entityName);
354
360
  }
355
361
  const entity = result.data[0];
356
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, entity);
362
+ const data = toDto(responseDtoClass, entity);
357
363
  return {
358
364
  success: true,
359
365
  message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)} retrieved successfully`,
@@ -373,7 +379,7 @@ function createApiController(createDtoClass, updateDtoClass, responseDtoClass, o
373
379
  });
374
380
  }
375
381
  const result = await this.service.getAll(search ?? '', filterAndPaginationDto, user);
376
- const data = (0, _classtransformer.plainToInstance)(responseDtoClass, result.data);
382
+ const data = result.data.map((item)=>toDto(responseDtoClass, item));
377
383
  const page = filterAndPaginationDto.pagination?.currentPage ?? 0;
378
384
  const pageSize = filterAndPaginationDto.pagination?.pageSize ?? data.length;
379
385
  const totalPages = pageSize > 0 ? Math.ceil(result.total / pageSize) : 1;
@@ -13,6 +13,9 @@ const _typeorm = require("typeorm");
13
13
  const _constants = require("../constants");
14
14
  const _logactiondecorator = require("../decorators/log-action.decorator");
15
15
  const _dtos = require("../dtos");
16
+ const _interfaces = require("../interfaces");
17
+ const _utilsservice = require("../modules/utils/utils.service");
18
+ const _hybridcacheclass = require("./hybrid-cache.class");
16
19
  function _define_property(obj, key, value) {
17
20
  if (key in obj) {
18
21
  Object.defineProperty(obj, key, {
@@ -36,6 +39,31 @@ function _ts_metadata(k, v) {
36
39
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
37
40
  }
38
41
  let ApiService = class ApiService {
42
+ resolveEntity() {
43
+ return this._entity;
44
+ }
45
+ getDataSourceProvider() {
46
+ return this._dataSourceProvider;
47
+ }
48
+ async ensureDataSourceRepository() {
49
+ if (!this.repositoryInitialized) {
50
+ const entity = this.resolveEntity();
51
+ const provider = this.getDataSourceProvider();
52
+ this.repository = await provider.getRepository(entity);
53
+ this.repositoryInitialized = true;
54
+ }
55
+ }
56
+ async resolveRepositories(entities) {
57
+ const provider = this.getDataSourceProvider();
58
+ const repositories = [];
59
+ for (const entity of entities){
60
+ repositories.push(await provider.getRepository(entity));
61
+ }
62
+ return repositories;
63
+ }
64
+ async getDataSourceForService() {
65
+ return this.getDataSourceProvider().getDataSource();
66
+ }
39
67
  async insert(dto, user) {
40
68
  return this.executeInTransaction('insert', async (qr)=>{
41
69
  await this.beforeInsertOperation(dto, user, qr);
@@ -108,7 +136,7 @@ let ApiService = class ApiService {
108
136
  });
109
137
  }
110
138
  async findByIds(ids, user, select) {
111
- await this.ensureRepositoryInitialized();
139
+ await this.ensureDataSourceRepository();
112
140
  try {
113
141
  const query = this.repository.createQueryBuilder(this.entityName);
114
142
  query.where({
@@ -136,7 +164,7 @@ let ApiService = class ApiService {
136
164
  }
137
165
  }
138
166
  async findById(id, user, select) {
139
- await this.ensureRepositoryInitialized();
167
+ await this.ensureDataSourceRepository();
140
168
  try {
141
169
  const query = this.repository.createQueryBuilder(this.entityName);
142
170
  query.where({
@@ -150,18 +178,17 @@ let ApiService = class ApiService {
150
178
  result = await this.cacheManager.get(cacheKey);
151
179
  }
152
180
  if (!result) {
153
- let output;
154
181
  if (isRaw) {
155
- output = await finalQuery.getRawMany();
156
- const convertResult = this.convertEntityListToResponseListDto(output, isRaw);
182
+ const rawOutput = await finalQuery.getRawMany();
183
+ const convertResult = this.convertEntityListToResponseListDto(rawOutput, isRaw);
157
184
  if (convertResult.length) result = convertResult[0];
158
185
  } else {
159
- output = await finalQuery.getOne();
160
- if (!output) throw new _common.NotFoundException({
186
+ const singleOutput = await finalQuery.getOne();
187
+ if (!singleOutput) throw new _common.NotFoundException({
161
188
  message: 'No Data Found',
162
189
  messageKey: _constants.ERROR_MESSAGES.NOT_FOUND
163
190
  });
164
- result = this.convertEntityToResponseDto(output, false);
191
+ result = this.convertEntityToResponseDto(singleOutput, false);
165
192
  }
166
193
  if (this.isCacheable) {
167
194
  await this.cacheManager.set(cacheKey, result);
@@ -177,43 +204,34 @@ let ApiService = class ApiService {
177
204
  }
178
205
  }
179
206
  async getAll(search, filterAndPaginationDto, user) {
180
- await this.ensureRepositoryInitialized();
207
+ await this.ensureDataSourceRepository();
181
208
  try {
182
209
  let data;
183
210
  let total;
184
211
  let isRaw = false;
185
212
  let query = this.repository.createQueryBuilder(this.entityName);
186
- // Apply filters
187
213
  if (filterAndPaginationDto.filter) {
188
214
  const { query: filterQuery, isRaw: filterIsRaw } = await this.getFilterQuery(query, filterAndPaginationDto.filter, user);
189
215
  query = filterQuery;
190
216
  isRaw = isRaw || filterIsRaw;
191
217
  }
192
- // Apply search
193
218
  if (search) {
194
219
  const { query: searchQuery, isRaw: searchIsRaw } = await this.getGlobalSearchQuery(query, search, user);
195
220
  query = searchQuery;
196
221
  isRaw = isRaw || searchIsRaw;
197
222
  }
198
- // Apply select
199
- if (filterAndPaginationDto.select) {
200
- const { query: selectQuery, isRaw: selectIsRaw } = await this.getSelectQuery(query, user, filterAndPaginationDto.select);
201
- query = selectQuery;
202
- isRaw = isRaw || selectIsRaw;
203
- }
204
- // Apply sort
223
+ const { query: selectQuery, isRaw: selectIsRaw } = await this.getSelectQuery(query, user, filterAndPaginationDto.select);
224
+ query = selectQuery;
225
+ isRaw = isRaw || selectIsRaw;
205
226
  if (filterAndPaginationDto.sort) {
206
227
  const { query: sortQuery, isRaw: sortIsRaw } = await this.getSortQuery(query, filterAndPaginationDto.sort, user);
207
228
  query = sortQuery;
208
229
  isRaw = isRaw || sortIsRaw;
209
230
  }
210
- // Include soft-deleted if requested
211
231
  if (filterAndPaginationDto.withDeleted) query.withDeleted();
212
- // Extra manipulation
213
232
  const { query: extraQuery, isRaw: extraIsRaw } = await this.getExtraManipulateQuery(query, filterAndPaginationDto, user);
214
233
  query = extraQuery;
215
234
  isRaw = isRaw || extraIsRaw;
216
- // Pagination
217
235
  if (filterAndPaginationDto.pagination) {
218
236
  const offset = filterAndPaginationDto.pagination.currentPage * filterAndPaginationDto.pagination.pageSize;
219
237
  const limit = filterAndPaginationDto.pagination.pageSize;
@@ -223,7 +241,6 @@ let ApiService = class ApiService {
223
241
  query.skip(offset).take(limit);
224
242
  }
225
243
  }
226
- // Generate cache key
227
244
  let cacheKey = '';
228
245
  if (this.isCacheable) {
229
246
  cacheKey = this.utilsService.getCacheKey(this.entityName, {
@@ -237,7 +254,6 @@ let ApiService = class ApiService {
237
254
  }
238
255
  }
239
256
  if (isRaw) {
240
- // Handle raw query count manually
241
257
  const rawSubQuery = query.clone().offset(undefined).limit(undefined).distinct(true);
242
258
  const countSql = `
243
259
  SELECT COUNT(*) as count
@@ -285,7 +301,7 @@ let ApiService = class ApiService {
285
301
  }
286
302
  }
287
303
  async delete(option, user) {
288
- await this.ensureRepositoryInitialized();
304
+ await this.ensureDataSourceRepository();
289
305
  const queryRunner = this.repository.manager.connection.createQueryRunner();
290
306
  await queryRunner.connect();
291
307
  await queryRunner.startTransaction();
@@ -317,7 +333,6 @@ let ApiService = class ApiService {
317
333
  this.clearCacheForAll(),
318
334
  this.clearCacheForId(ids)
319
335
  ]);
320
- // return null per IService contract
321
336
  return null;
322
337
  } catch (error) {
323
338
  await queryRunner.rollbackTransaction();
@@ -326,7 +341,6 @@ let ApiService = class ApiService {
326
341
  await queryRunner.release();
327
342
  }
328
343
  }
329
- // Caching
330
344
  async clearCacheForAll() {
331
345
  await this.utilsService.clearCache(this.entityName, this.cacheManager);
332
346
  }
@@ -342,13 +356,13 @@ let ApiService = class ApiService {
342
356
  messageKey: _constants.ERROR_MESSAGES.INTERNAL
343
357
  });
344
358
  }
345
- /** Ensures value is always an array */ ensureArray(value) {
359
+ ensureArray(value) {
346
360
  return Array.isArray(value) ? value : [
347
361
  value
348
362
  ];
349
363
  }
350
- /** Executes operation in transaction with automatic cache clearing */ async executeInTransaction(operation, fn) {
351
- await this.ensureRepositoryInitialized();
364
+ async executeInTransaction(operation, fn) {
365
+ await this.ensureDataSourceRepository();
352
366
  const qr = this.repository.manager.connection.createQueryRunner();
353
367
  await qr.connect();
354
368
  await qr.startTransaction();
@@ -373,8 +387,6 @@ let ApiService = class ApiService {
373
387
  await qr.release();
374
388
  }
375
389
  }
376
- // Hooks (override in child classes)
377
- async ensureRepositoryInitialized() {}
378
390
  async beforeInsertOperation(_dto, _user, _queryRunner) {}
379
391
  async afterInsertOperation(_entity, _user, _queryRunner) {}
380
392
  async beforeUpdateOperation(_dto, _user, _queryRunner) {}
@@ -423,7 +435,6 @@ let ApiService = class ApiService {
423
435
  isRaw: false
424
436
  };
425
437
  }
426
- // DTO conversion
427
438
  async convertRequestDtoToEntity(dto, user) {
428
439
  return Array.isArray(dto) ? await this.convertArrayDtoToEntities(dto, user) : [
429
440
  await this.convertSingleDtoToEntity(dto, user)
@@ -458,21 +469,26 @@ let ApiService = class ApiService {
458
469
  async getEntityClass() {
459
470
  return await this.repository.create();
460
471
  }
461
- constructor(entityName, repository, cacheManager, utilsService, _loggerName, isCacheable = false, moduleName){
472
+ constructor(entityName, cacheManager, utilsService, _loggerName, isCacheable = false, moduleName, entity, dataSourceProvider){
462
473
  _define_property(this, "entityName", void 0);
463
- _define_property(this, "repository", void 0);
464
474
  _define_property(this, "cacheManager", void 0);
465
475
  _define_property(this, "utilsService", void 0);
466
476
  _define_property(this, "_loggerName", void 0);
467
477
  _define_property(this, "isCacheable", void 0);
468
478
  _define_property(this, "moduleName", void 0);
479
+ _define_property(this, "repository", void 0);
480
+ _define_property(this, "repositoryInitialized", void 0);
481
+ _define_property(this, "_entity", void 0);
482
+ _define_property(this, "_dataSourceProvider", void 0);
469
483
  this.entityName = entityName;
470
- this.repository = repository;
471
484
  this.cacheManager = cacheManager;
472
485
  this.utilsService = utilsService;
473
486
  this._loggerName = _loggerName;
474
487
  this.isCacheable = isCacheable;
475
488
  this.moduleName = moduleName;
489
+ this.repositoryInitialized = false;
490
+ this._entity = entity;
491
+ this._dataSourceProvider = dataSourceProvider;
476
492
  }
477
493
  };
478
494
  _ts_decorate([
@@ -542,3 +558,19 @@ _ts_decorate([
542
558
  ]),
543
559
  _ts_metadata("design:returntype", Promise)
544
560
  ], ApiService.prototype, "delete", null);
561
+ ApiService = _ts_decorate([
562
+ (0, _common.Injectable)({
563
+ scope: _common.Scope.REQUEST
564
+ }),
565
+ _ts_metadata("design:type", Function),
566
+ _ts_metadata("design:paramtypes", [
567
+ String,
568
+ typeof _hybridcacheclass.HybridCache === "undefined" ? Object : _hybridcacheclass.HybridCache,
569
+ typeof _utilsservice.UtilsService === "undefined" ? Object : _utilsservice.UtilsService,
570
+ String,
571
+ Boolean,
572
+ String,
573
+ typeof _typeorm.EntityTarget === "undefined" ? Object : _typeorm.EntityTarget,
574
+ typeof _interfaces.IDataSourceProvider === "undefined" ? Object : _interfaces.IDataSourceProvider
575
+ ])
576
+ ], ApiService);
@@ -6,7 +6,6 @@ _export_star(require("./api-controller.class"), exports);
6
6
  _export_star(require("./api-service.class"), exports);
7
7
  _export_star(require("./handle-custome-db-column-type"), exports);
8
8
  _export_star(require("./hybrid-cache.class"), exports);
9
- _export_star(require("./request-scoped-api.service"), exports);
10
9
  _export_star(require("./winston.logger.class"), exports);
11
10
  _export_star(require("../constants/permissions"), exports);
12
11
  function _export_star(from, to) {
@@ -8,8 +8,8 @@ Object.defineProperty(exports, "IdentityResponseDto", {
8
8
  return IdentityResponseDto;
9
9
  }
10
10
  });
11
- const _classtransformer = require("class-transformer");
12
11
  const _swagger = require("@nestjs/swagger");
12
+ const _classtransformer = require("class-transformer");
13
13
  function _define_property(obj, key, value) {
14
14
  if (key in obj) {
15
15
  Object.defineProperty(obj, key, {
@@ -44,28 +44,28 @@ let IdentityResponseDto = class IdentityResponseDto {
44
44
  }
45
45
  };
46
46
  _ts_decorate([
47
+ (0, _classtransformer.Expose)(),
47
48
  (0, _swagger.ApiProperty)({
48
49
  type: String,
49
50
  format: 'uuid'
50
51
  }),
51
- (0, _classtransformer.Expose)(),
52
52
  _ts_metadata("design:type", String)
53
53
  ], IdentityResponseDto.prototype, "id", void 0);
54
54
  _ts_decorate([
55
+ (0, _classtransformer.Expose)(),
55
56
  (0, _swagger.ApiProperty)({
56
57
  type: String,
57
58
  format: 'date-time'
58
59
  }),
59
- (0, _classtransformer.Expose)(),
60
60
  (0, _classtransformer.Type)(()=>Date),
61
61
  _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
62
62
  ], IdentityResponseDto.prototype, "createdAt", void 0);
63
63
  _ts_decorate([
64
+ (0, _classtransformer.Expose)(),
64
65
  (0, _swagger.ApiProperty)({
65
66
  type: String,
66
67
  format: 'date-time'
67
68
  }),
68
- (0, _classtransformer.Expose)(),
69
69
  (0, _classtransformer.Type)(()=>Date),
70
70
  _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
71
71
  ], IdentityResponseDto.prototype, "updatedAt", void 0);
@@ -76,7 +76,6 @@ _ts_decorate([
76
76
  nullable: true,
77
77
  required: false
78
78
  }),
79
- (0, _classtransformer.Expose)(),
80
79
  (0, _classtransformer.Type)(()=>Date),
81
80
  _ts_metadata("design:type", Object)
82
81
  ], IdentityResponseDto.prototype, "deletedAt", void 0);
@@ -87,7 +86,6 @@ _ts_decorate([
87
86
  nullable: true,
88
87
  required: false
89
88
  }),
90
- (0, _classtransformer.Expose)(),
91
89
  _ts_metadata("design:type", Object)
92
90
  ], IdentityResponseDto.prototype, "createdById", void 0);
93
91
  _ts_decorate([
@@ -97,7 +95,6 @@ _ts_decorate([
97
95
  nullable: true,
98
96
  required: false
99
97
  }),
100
- (0, _classtransformer.Expose)(),
101
98
  _ts_metadata("design:type", Object)
102
99
  ], IdentityResponseDto.prototype, "updatedById", void 0);
103
100
  _ts_decorate([
@@ -107,6 +104,5 @@ _ts_decorate([
107
104
  nullable: true,
108
105
  required: false
109
106
  }),
110
- (0, _classtransformer.Expose)(),
111
107
  _ts_metadata("design:type", Object)
112
108
  ], IdentityResponseDto.prototype, "deletedById", void 0);
@@ -49,14 +49,16 @@ _ts_decorate([
49
49
  _ts_decorate([
50
50
  (0, _typeorm.CreateDateColumn)({
51
51
  name: 'created_at',
52
- type: 'timestamp'
52
+ type: 'timestamp',
53
+ select: false
53
54
  }),
54
55
  _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
55
56
  ], Identity.prototype, "createdAt", void 0);
56
57
  _ts_decorate([
57
58
  (0, _typeorm.UpdateDateColumn)({
58
59
  name: 'updated_at',
59
- type: 'timestamp'
60
+ type: 'timestamp',
61
+ select: false
60
62
  }),
61
63
  _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
62
64
  ], Identity.prototype, "updatedAt", void 0);
@@ -64,6 +66,7 @@ _ts_decorate([
64
66
  (0, _typeorm.DeleteDateColumn)({
65
67
  name: 'deleted_at',
66
68
  type: 'timestamp',
69
+ select: false,
67
70
  nullable: true
68
71
  }),
69
72
  _ts_metadata("design:type", Object)
@@ -72,6 +75,7 @@ _ts_decorate([
72
75
  (0, _typeorm.Column)({
73
76
  name: 'created_by_id',
74
77
  type: 'uuid',
78
+ select: false,
75
79
  nullable: true
76
80
  }),
77
81
  _ts_metadata("design:type", Object)
@@ -80,6 +84,7 @@ _ts_decorate([
80
84
  (0, _typeorm.Column)({
81
85
  name: 'updated_by_id',
82
86
  type: 'uuid',
87
+ select: false,
83
88
  nullable: true
84
89
  }),
85
90
  _ts_metadata("design:type", Object)
@@ -88,6 +93,7 @@ _ts_decorate([
88
93
  (0, _typeorm.Column)({
89
94
  name: 'deleted_by_id',
90
95
  type: 'uuid',
96
+ select: false,
91
97
  nullable: true
92
98
  }),
93
99
  _ts_metadata("design:type", Object)
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- _export_star(require("./datasource.module"), exports);
6
5
  _export_star(require("./multi-tenant-datasource.service"), exports);
7
6
  function _export_star(from, to) {
8
7
  Object.keys(from).forEach(function(k) {
@@ -43,21 +43,21 @@ function _ts_param(paramIndex, decorator) {
43
43
  };
44
44
  }
45
45
  let MultiTenantDataSourceService = class MultiTenantDataSourceService {
46
+ get self() {
47
+ return this.constructor;
48
+ }
46
49
  initializeFromOptions() {
47
50
  if (!this.options) return;
48
- if (!MultiTenantDataSourceService.initialized) {
51
+ if (!this.self.initialized) {
49
52
  this.registerTenants();
50
- MultiTenantDataSourceService.initialized = true;
53
+ this.self.initialized = true;
51
54
  }
52
55
  }
53
56
  registerTenants() {
54
57
  this.options?.tenants?.forEach((tenant)=>{
55
- MultiTenantDataSourceService.tenantsRegistry.set(tenant.id, tenant);
58
+ this.self.tenantsRegistry.set(tenant.id, tenant);
56
59
  });
57
60
  }
58
- setTenantHeader(header) {
59
- this.tenantHeader = header;
60
- }
61
61
  getDatabaseMode() {
62
62
  return this.options?.bootstrapAppConfig?.databaseMode ?? 'single';
63
63
  }
@@ -81,91 +81,33 @@ let MultiTenantDataSourceService = class MultiTenantDataSourceService {
81
81
  return tenantId ? this.getTenant(tenantId) : null;
82
82
  }
83
83
  getTenant(tenantId) {
84
- return MultiTenantDataSourceService.tenantsRegistry.get(tenantId) ?? null;
85
- }
86
- getAllTenants() {
87
- return Array.from(MultiTenantDataSourceService.tenantsRegistry.values());
88
- }
89
- getActiveTenants() {
90
- return this.getAllTenants();
84
+ return this.self.tenantsRegistry.get(tenantId) ?? null;
91
85
  }
92
86
  async getDataSource() {
93
87
  return this.isMultiTenant() ? this.getTenantDataSource() : this.getSingleDataSource();
94
88
  }
95
- async getDataSourceForTenant(tenantId) {
96
- const tenant = this.getTenant(tenantId);
97
- if (!tenant) {
98
- throw new _common.BadRequestException({
99
- message: `Tenant '${tenantId}' not found`,
100
- messageKey: _constants.SYSTEM_MESSAGES.TENANT_NOT_FOUND,
101
- messageVariables: {
102
- tenantId
103
- }
104
- });
105
- }
106
- return this.getOrCreateTenantConnection(tenant);
107
- }
108
- setDataSource(dataSource) {
109
- MultiTenantDataSourceService.singleDataSource = dataSource;
110
- }
111
89
  async getRepository(entity) {
112
90
  const dataSource = await this.getDataSource();
113
91
  return dataSource.getRepository(entity);
114
92
  }
115
- async withTenant(tenantId, callback) {
116
- const dataSource = await this.getDataSourceForTenant(tenantId);
117
- return callback(dataSource);
118
- }
119
- async forAllTenants(callback) {
120
- const results = new Map();
121
- for (const tenant of this.getActiveTenants()){
122
- try {
123
- const dataSource = await this.getOrCreateTenantConnection(tenant);
124
- results.set(tenant.id, await callback(tenant, dataSource));
125
- } catch {
126
- // Silent failure for individual tenant
127
- }
128
- }
129
- return results;
130
- }
131
- registerTenant(tenant) {
132
- MultiTenantDataSourceService.tenantsRegistry.set(tenant.id, tenant);
133
- }
134
- async removeTenant(tenantId) {
135
- await this.closeTenantConnection(tenantId);
136
- MultiTenantDataSourceService.tenantsRegistry.delete(tenantId);
137
- }
138
93
  async closeTenantConnection(tenantId) {
139
- const connection = MultiTenantDataSourceService.tenantConnections.get(tenantId);
94
+ const connection = this.self.tenantConnections.get(tenantId);
140
95
  if (connection?.isInitialized) {
141
96
  await connection.destroy();
142
- MultiTenantDataSourceService.tenantConnections.delete(tenantId);
97
+ this.self.tenantConnections.delete(tenantId);
143
98
  }
144
99
  }
145
100
  async onModuleDestroy() {
146
- for (const [tenantId] of MultiTenantDataSourceService.tenantConnections){
101
+ for (const [tenantId] of this.self.tenantConnections){
147
102
  await this.closeTenantConnection(tenantId);
148
103
  }
149
104
  }
150
- static reset() {
151
- MultiTenantDataSourceService.initialized = false;
152
- MultiTenantDataSourceService.singleDataSource = null;
153
- MultiTenantDataSourceService.singleConnectionLock = null;
154
- MultiTenantDataSourceService.tenantConnections.clear();
155
- MultiTenantDataSourceService.tenantsRegistry.clear();
156
- MultiTenantDataSourceService.connectionLocks.clear();
157
- }
158
- // Protected Methods (for subclasses)
159
- /**
160
- * Get single database DataSource with connection locking to prevent race conditions
161
- */ async getSingleDataSource() {
162
- // Return existing initialized connection
163
- if (MultiTenantDataSourceService.singleDataSource?.isInitialized) {
164
- return MultiTenantDataSourceService.singleDataSource;
105
+ async getSingleDataSource() {
106
+ if (this.self.singleDataSource?.isInitialized) {
107
+ return this.self.singleDataSource;
165
108
  }
166
- // If another request is creating the connection, wait for it
167
- if (MultiTenantDataSourceService.singleConnectionLock) {
168
- return MultiTenantDataSourceService.singleConnectionLock;
109
+ if (this.self.singleConnectionLock) {
110
+ return this.self.singleConnectionLock;
169
111
  }
170
112
  const config = this.getDefaultDatabaseConfig();
171
113
  if (!config) {
@@ -174,20 +116,17 @@ let MultiTenantDataSourceService = class MultiTenantDataSourceService {
174
116
  messageKey: _constants.SYSTEM_MESSAGES.DATABASE_CONFIG_NOT_AVAILABLE
175
117
  });
176
118
  }
177
- // Create connection with lock to prevent race conditions
178
119
  const connectionPromise = this.createDataSourceFromConfig(config);
179
- MultiTenantDataSourceService.singleConnectionLock = connectionPromise;
120
+ this.self.singleConnectionLock = connectionPromise;
180
121
  try {
181
122
  const dataSource = await connectionPromise;
182
- MultiTenantDataSourceService.singleDataSource = dataSource;
123
+ this.self.singleDataSource = dataSource;
183
124
  return dataSource;
184
125
  } finally{
185
- MultiTenantDataSourceService.singleConnectionLock = null;
126
+ this.self.singleConnectionLock = null;
186
127
  }
187
128
  }
188
- /**
189
- * Get tenant-specific DataSource
190
- */ async getTenantDataSource() {
129
+ async getTenantDataSource() {
191
130
  const tenant = this.getCurrentTenant();
192
131
  if (!tenant) {
193
132
  throw new _common.BadRequestException({
@@ -201,19 +140,19 @@ let MultiTenantDataSourceService = class MultiTenantDataSourceService {
201
140
  return this.getOrCreateTenantConnection(tenant);
202
141
  }
203
142
  async getOrCreateTenantConnection(tenant) {
204
- const existing = MultiTenantDataSourceService.tenantConnections.get(tenant.id);
143
+ const existing = this.self.tenantConnections.get(tenant.id);
205
144
  if (existing?.isInitialized) return existing;
206
- const pendingConnection = MultiTenantDataSourceService.connectionLocks.get(tenant.id);
145
+ const pendingConnection = this.self.connectionLocks.get(tenant.id);
207
146
  if (pendingConnection) return pendingConnection;
208
147
  const config = this.buildTenantDatabaseConfig(tenant);
209
148
  const connectionPromise = this.createDataSourceFromConfig(config);
210
- MultiTenantDataSourceService.connectionLocks.set(tenant.id, connectionPromise);
149
+ this.self.connectionLocks.set(tenant.id, connectionPromise);
211
150
  try {
212
151
  const dataSource = await connectionPromise;
213
- MultiTenantDataSourceService.tenantConnections.set(tenant.id, dataSource);
152
+ this.self.tenantConnections.set(tenant.id, dataSource);
214
153
  return dataSource;
215
154
  } finally{
216
- MultiTenantDataSourceService.connectionLocks.delete(tenant.id);
155
+ this.self.connectionLocks.delete(tenant.id);
217
156
  }
218
157
  }
219
158
  getDefaultDatabaseConfig() {