@flusys/nestjs-shared 8.1.5 → 9.0.1

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 (41) hide show
  1. package/README.md +48 -2
  2. package/classes/api-service.class.d.ts +3 -0
  3. package/constants/permissions.d.ts +46 -0
  4. package/exceptions/base-app.exception.d.ts +3 -2
  5. package/fesm/{509.js → 183.js} +43 -37
  6. package/fesm/470.js +228 -105
  7. package/fesm/667.js +28 -10
  8. package/fesm/{67.js → 681.js} +97 -19
  9. package/fesm/{720.js → 948.js} +60 -7
  10. package/fesm/chunks/123.js +9 -10
  11. package/fesm/chunks/37.js +7 -8
  12. package/fesm/classes/index.js +10 -4
  13. package/fesm/constants/index.js +53 -1
  14. package/fesm/decorators/index.js +4 -4
  15. package/fesm/dtos/index.js +2 -2
  16. package/fesm/guards/index.js +48 -426
  17. package/fesm/index.js +436 -341
  18. package/fesm/interceptors/index.js +62 -23
  19. package/fesm/interfaces/index.js +28 -3
  20. package/fesm/middlewares/index.js +5 -3
  21. package/fesm/modules/index.js +6 -414
  22. package/fesm/pipes/index.js +196 -0
  23. package/fesm/utils/index.js +125 -10
  24. package/index.d.ts +1 -0
  25. package/interfaces/company-access-resolver.interface.d.ts +18 -0
  26. package/interfaces/datasource.interface.d.ts +2 -0
  27. package/interfaces/email-adapter.interface.d.ts +27 -0
  28. package/interfaces/index.d.ts +5 -0
  29. package/interfaces/message-ref.interface.d.ts +4 -0
  30. package/interfaces/permission-action-registry.interface.d.ts +12 -0
  31. package/interfaces/permission-resolver.interface.d.ts +9 -0
  32. package/middlewares/logger.middleware.d.ts +4 -0
  33. package/modules/shared-permission-cache/shared-permission-cache.service.d.ts +5 -0
  34. package/package.json +9 -3
  35. package/pipes/dto-body-validation.pipe.d.ts +18 -0
  36. package/pipes/index.d.ts +1 -0
  37. package/utils/cache-tenant.util.d.ts +2 -0
  38. package/utils/index.d.ts +3 -0
  39. package/utils/message-ref.util.d.ts +2 -0
  40. package/utils/permission-match.util.d.ts +1 -0
  41. package/utils/query-helpers.util.d.ts +2 -1
package/fesm/470.js CHANGED
@@ -1,4 +1,3 @@
1
- import * as __rspack_external_crypto from "crypto";
2
1
  import * as __rspack_external__nestjs_passport_18907953 from "@nestjs/passport";
3
2
  import * as __rspack_external_rxjs from "rxjs";
4
3
  import * as __rspack_external_rxjs_operators_2eaa0997 from "rxjs/operators";
@@ -49,10 +48,14 @@ __webpack_require__.d(__webpack_exports__, {
49
48
  XI: () => (/* reexport */ disabled_event_bus_class/* .DisabledEventBus */.X),
50
49
  V0: () => (/* reexport */ permissions/* .EMAIL_CONFIG_PERMISSIONS */.V0),
51
50
  z$: () => (/* reexport */ permissions/* .EMAIL_TEMPLATE_PERMISSIONS */.z$),
51
+ G0: () => (/* reexport */ permissions/* .ENTITY_BUILDER_ALL_DYNAMIC */.G0),
52
+ DP: () => (/* reexport */ permissions/* .ENTITY_DEFINITION_PERMISSIONS */.DP),
52
53
  Ub: () => (/* reexport */ permissions/* .EVENT_PERMISSIONS */.Ub),
53
54
  qS: () => (/* reexport */ event_bus_registry/* .EventBusRegistry */.q),
54
55
  Pm: () => (/* reexport */ event_transport_registry/* .EventTransportRegistry */.P),
56
+ kA: () => (/* reexport */ permissions/* .FIELD_DEFINITION_PERMISSIONS */.kA),
55
57
  S6: () => (/* reexport */ permissions/* .FILE_PERMISSIONS */.S6),
58
+ kd: () => (/* reexport */ permissions/* .FLOW_DEFINITION_PERMISSIONS */.kd),
56
59
  wM: () => (/* reexport */ permissions/* .FOLDER_PERMISSIONS */.wM),
57
60
  Wc: () => (/* reexport */ permissions/* .FORM_PERMISSIONS */.Wc),
58
61
  GT: () => (/* reexport */ permissions/* .FORM_RESULT_PERMISSIONS */.GT),
@@ -81,6 +84,8 @@ __webpack_require__.d(__webpack_exports__, {
81
84
  Zq: () => (/* reexport */ handle_custome_db/* .buildQuery */.Zq),
82
85
  RD: () => (/* reexport */ createApiController),
83
86
  Xv: () => (/* reexport */ winston_logger_class/* .createModuleLogger */.X),
87
+ aT: () => (/* reexport */ permissions/* .dynamicEntityPermission */.aT),
88
+ GH: () => (/* reexport */ permissions/* .dynamicEntityPermissionParent */.GH),
84
89
  Tj: () => (/* reexport */ handle_custome_db/* .getCastIntType */.Tj),
85
90
  pf: () => (/* reexport */ handle_custome_db/* .getJsonColumnType */.pf),
86
91
  KJ: () => (/* reexport */ winston_logger_class/* .instance */.K),
@@ -99,14 +104,16 @@ var message_keys = __webpack_require__(389);
99
104
  var src_decorators = __webpack_require__(523);
100
105
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/decorators/api-response.decorator.ts
101
106
  var api_response_decorator = __webpack_require__(997);
102
- // EXTERNAL MODULE: ./projects/nestjs-shared/src/dtos/index.ts + 7 modules
103
- var src_dtos = __webpack_require__(980);
107
+ // EXTERNAL MODULE: ./projects/nestjs-shared/src/dtos/index.ts + 6 modules
108
+ var src_dtos = __webpack_require__(746);
104
109
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/exceptions/index.ts
105
110
  var exceptions = __webpack_require__(448);
106
111
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/guards/index.ts + 4 modules
107
112
  var guards = __webpack_require__(510);
108
113
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/interceptors/index.ts + 7 modules
109
114
  var interceptors = __webpack_require__(863);
115
+ // EXTERNAL MODULE: ./projects/nestjs-shared/src/pipes/index.ts + 1 modules
116
+ var pipes = __webpack_require__(928);
110
117
  ;// CONCATENATED MODULE: ./projects/nestjs-shared/src/classes/api-controller.class.ts
111
118
  function _ts_decorate(decorators, target, key, desc) {
112
119
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -141,6 +148,7 @@ function _ts_param(paramIndex, decorator) {
141
148
 
142
149
 
143
150
 
151
+
144
152
  /**
145
153
  * Helper to normalize security config
146
154
  */ function normalizeSecurity(config) {
@@ -212,6 +220,22 @@ function _ts_param(paramIndex, decorator) {
212
220
  }
213
221
  // Entity name for message keys (defaults to 'item')
214
222
  const entityName = options.entityName ?? 'item';
223
+ const insertBodyPipe = pipes/* .DtoBodyValidationPipe["for"] */.zT["for"](createDtoClass, [
224
+ 'createdById'
225
+ ]);
226
+ const insertManyBodyPipe = pipes/* .DtoBodyValidationPipe["for"] */.zT["for"](createDtoClass, [
227
+ 'createdById'
228
+ ], true);
229
+ const updateBodyPipe = pipes/* .DtoBodyValidationPipe["for"] */.zT["for"](updateDtoClass, [
230
+ 'updatedById'
231
+ ]);
232
+ const updateManyBodyPipe = pipes/* .DtoBodyValidationPipe["for"] */.zT["for"](updateDtoClass, [
233
+ 'updatedById'
234
+ ], true);
235
+ const bulkUpsertBodyPipe = new pipes/* .DtoBodyValidationPipe */.zT((item)=>item.id ? updateDtoClass : createDtoClass, [
236
+ 'createdById',
237
+ 'updatedById'
238
+ ], true);
215
239
  // Determine if security is global (applies to all) or per-endpoint
216
240
  const securityConfig = options.security;
217
241
  const endpointKeys = [
@@ -542,7 +566,7 @@ function _ts_param(paramIndex, decorator) {
542
566
  type: createDtoClass
543
567
  }),
544
568
  (0,common_.UseInterceptors)(interceptors/* .IdempotencyInterceptor */.Bw, interceptors/* .SetCreatedByOnBody */.VS, interceptors/* .Slug */.Mw),
545
- _ts_param(0, (0,common_.Body)()),
569
+ _ts_param(0, (0,common_.Body)(insertBodyPipe)),
546
570
  _ts_param(1, (0,src_decorators/* .CurrentUser */.NO)()),
547
571
  _ts_metadata("design:type", Function),
548
572
  _ts_metadata("design:paramtypes", [
@@ -571,7 +595,7 @@ function _ts_param(paramIndex, decorator) {
571
595
  isArray: true
572
596
  }),
573
597
  (0,common_.UseInterceptors)(interceptors/* .IdempotencyInterceptor */.Bw, interceptors/* .SetCreatedByOnBody */.VS, interceptors/* .Slug */.Mw),
574
- _ts_param(0, (0,common_.Body)()),
598
+ _ts_param(0, (0,common_.Body)(insertManyBodyPipe)),
575
599
  _ts_param(1, (0,src_decorators/* .CurrentUser */.NO)()),
576
600
  _ts_metadata("design:type", Function),
577
601
  _ts_metadata("design:paramtypes", [
@@ -646,7 +670,7 @@ function _ts_param(paramIndex, decorator) {
646
670
  type: updateDtoClass
647
671
  }),
648
672
  (0,common_.UseInterceptors)(interceptors/* .SetUpdateByOnBody */._x, interceptors/* .Slug */.Mw),
649
- _ts_param(0, (0,common_.Body)()),
673
+ _ts_param(0, (0,common_.Body)(updateBodyPipe)),
650
674
  _ts_param(1, (0,src_decorators/* .CurrentUser */.NO)()),
651
675
  _ts_metadata("design:type", Function),
652
676
  _ts_metadata("design:paramtypes", [
@@ -670,7 +694,7 @@ function _ts_param(paramIndex, decorator) {
670
694
  isArray: true
671
695
  }),
672
696
  (0,common_.UseInterceptors)(interceptors/* .SetUpdateByOnBody */._x, interceptors/* .Slug */.Mw),
673
- _ts_param(0, (0,common_.Body)()),
697
+ _ts_param(0, (0,common_.Body)(updateManyBodyPipe)),
674
698
  _ts_param(1, (0,src_decorators/* .CurrentUser */.NO)()),
675
699
  _ts_metadata("design:type", Function),
676
700
  _ts_metadata("design:paramtypes", [
@@ -694,7 +718,7 @@ function _ts_param(paramIndex, decorator) {
694
718
  isArray: true
695
719
  }),
696
720
  (0,common_.UseInterceptors)(interceptors/* .SetCreatedByOnBody */.VS, interceptors/* .SetUpdateByOnBody */._x, interceptors/* .Slug */.Mw),
697
- _ts_param(0, (0,common_.Body)()),
721
+ _ts_param(0, (0,common_.Body)(bulkUpsertBodyPipe)),
698
722
  _ts_param(1, (0,src_decorators/* .CurrentUser */.NO)()),
699
723
  _ts_metadata("design:type", Function),
700
724
  _ts_metadata("design:paramtypes", [
@@ -824,14 +848,18 @@ function _ts_param(paramIndex, decorator) {
824
848
 
825
849
  // EXTERNAL MODULE: external "typeorm"
826
850
  var external_typeorm_ = __webpack_require__(158);
851
+ // EXTERNAL MODULE: ./projects/nestjs-shared/src/constants/index.ts
852
+ var constants = __webpack_require__(43);
827
853
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/decorators/log-action.decorator.ts
828
854
  var log_action_decorator = __webpack_require__(946);
829
855
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/modules/utils/utils.service.ts
830
856
  var utils_service = __webpack_require__(169);
857
+ // EXTERNAL MODULE: ./projects/nestjs-shared/src/utils/cache-tenant.util.ts
858
+ var cache_tenant_util = __webpack_require__(154);
831
859
  // EXTERNAL MODULE: external "crypto"
832
860
  var external_crypto_ = __webpack_require__(823);
833
861
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/middlewares/logger.middleware.ts + 2 modules
834
- var logger_middleware = __webpack_require__(419);
862
+ var logger_middleware = __webpack_require__(591);
835
863
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/utils/event-pattern.util.ts
836
864
  var event_pattern_util = __webpack_require__(456);
837
865
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/classes/event-bus.registry.ts
@@ -930,6 +958,7 @@ function api_service_class_ts_metadata(metadataKey, metadataValue) {
930
958
 
931
959
 
932
960
 
961
+
933
962
  const DELETE_EVENT_ACTIONS = {
934
963
  delete: 'deleted',
935
964
  restore: 'restored',
@@ -963,6 +992,9 @@ class ApiService {
963
992
  getDataSourceProvider() {
964
993
  return this._dataSourceProvider;
965
994
  }
995
+ /** Cached rows belong to the current tenant; pass this to every `UtilsService` cache helper. */ cacheTenant() {
996
+ return (0,cache_tenant_util/* .cacheTenantId */.q)(this._dataSourceProvider);
997
+ }
966
998
  async ensureDataSourceRepository() {
967
999
  if (!this.repositoryInitialized) {
968
1000
  const provider = this.getDataSourceProvider();
@@ -1067,6 +1099,7 @@ class ApiService {
1067
1099
  id: (0,external_typeorm_.In)(ids)
1068
1100
  });
1069
1101
  const selectArray = typeof select === 'string' ? select.split(',').map((s)=>s.trim()) : select;
1102
+ selectArray?.forEach((field)=>this.assertColumnProperty(field));
1070
1103
  const { query: finalQuery, isRaw } = await this.getSelectQuery(query, user, selectArray);
1071
1104
  let output;
1072
1105
  if (isRaw) {
@@ -1077,7 +1110,7 @@ class ApiService {
1077
1110
  const result = this.convertEntityListToResponseListDto(output, isRaw);
1078
1111
  if (!result || !result.length) throw new common_.NotFoundException({
1079
1112
  message: 'No Data Found',
1080
- messageKey: message_keys/* .ERROR_MESSAGES.NOT_FOUND */.UU.NOT_FOUND
1113
+ messageKey: constants/* .ERROR_MESSAGES.NOT_FOUND */.UU.NOT_FOUND
1081
1114
  });
1082
1115
  return result;
1083
1116
  } catch (error) {
@@ -1090,6 +1123,7 @@ class ApiService {
1090
1123
  async findById(id, user, select) {
1091
1124
  await this.ensureDataSourceRepository();
1092
1125
  try {
1126
+ select?.forEach((field)=>this.assertColumnProperty(field));
1093
1127
  const query = this.repository.createQueryBuilder(this.entityName);
1094
1128
  query.where({
1095
1129
  id
@@ -1098,7 +1132,7 @@ class ApiService {
1098
1132
  let result;
1099
1133
  let cacheKey = '';
1100
1134
  if (this.isCacheable) {
1101
- cacheKey = this.utilsService.getCacheKey(this.entityName, finalQuery.getQueryAndParameters(), id);
1135
+ cacheKey = this.utilsService.getCacheKey(this.entityName, finalQuery.getQueryAndParameters(), id, this.cacheTenant());
1102
1136
  result = await this.cacheManager.get(cacheKey);
1103
1137
  }
1104
1138
  if (!result) {
@@ -1110,13 +1144,13 @@ class ApiService {
1110
1144
  const singleOutput = await finalQuery.getOne();
1111
1145
  if (!singleOutput) throw new common_.NotFoundException({
1112
1146
  message: 'No Data Found',
1113
- messageKey: message_keys/* .ERROR_MESSAGES.NOT_FOUND */.UU.NOT_FOUND
1147
+ messageKey: constants/* .ERROR_MESSAGES.NOT_FOUND */.UU.NOT_FOUND
1114
1148
  });
1115
1149
  result = this.convertEntityToResponseDto(singleOutput, false);
1116
1150
  }
1117
1151
  if (this.isCacheable) {
1118
1152
  await this.cacheManager.set(cacheKey, result);
1119
- await this.utilsService.trackCacheKey(cacheKey, this.entityName, this.cacheManager, id);
1153
+ await this.utilsService.trackCacheKey(cacheKey, this.entityName, this.cacheManager, id, this.cacheTenant());
1120
1154
  }
1121
1155
  }
1122
1156
  return result;
@@ -1133,6 +1167,7 @@ class ApiService {
1133
1167
  let data;
1134
1168
  let total;
1135
1169
  let isRaw = false;
1170
+ filterAndPaginationDto.select?.forEach((field)=>this.assertColumnProperty(field));
1136
1171
  let query = this.repository.createQueryBuilder(this.entityName);
1137
1172
  if (filterAndPaginationDto.filter) {
1138
1173
  const { query: filterQuery, isRaw: filterIsRaw } = await this.getFilterQuery(query, filterAndPaginationDto.filter, user);
@@ -1171,7 +1206,7 @@ class ApiService {
1171
1206
  raw: isRaw,
1172
1207
  pagination: filterAndPaginationDto.pagination,
1173
1208
  query: query.getQueryAndParameters()
1174
- });
1209
+ }, undefined, this.cacheTenant());
1175
1210
  const cached = await this.cacheManager.get(cacheKey);
1176
1211
  if (cached) {
1177
1212
  return cached;
@@ -1197,7 +1232,7 @@ class ApiService {
1197
1232
  if (!(key in parameters)) {
1198
1233
  throw new common_.InternalServerErrorException({
1199
1234
  message: `Missing parameter value for: ${key}`,
1200
- messageKey: message_keys/* .SYSTEM_MESSAGES.MISSING_PARAMETER */.hg.MISSING_PARAMETER,
1235
+ messageKey: constants/* .SYSTEM_MESSAGES.MISSING_PARAMETER */.hg.MISSING_PARAMETER,
1201
1236
  messageVariables: {
1202
1237
  key
1203
1238
  }
@@ -1219,7 +1254,7 @@ class ApiService {
1219
1254
  };
1220
1255
  if (this.isCacheable) {
1221
1256
  await this.cacheManager.set(cacheKey, finalResponse);
1222
- await this.utilsService.trackCacheKey(cacheKey, this.entityName, this.cacheManager);
1257
+ await this.utilsService.trackCacheKey(cacheKey, this.entityName, this.cacheManager, undefined, this.cacheTenant());
1223
1258
  }
1224
1259
  return finalResponse;
1225
1260
  } catch (error) {
@@ -1301,10 +1336,10 @@ class ApiService {
1301
1336
  });
1302
1337
  }
1303
1338
  async clearCacheForAll() {
1304
- await this.utilsService.clearCache(this.entityName, this.cacheManager);
1339
+ await this.utilsService.clearCache(this.entityName, this.cacheManager, undefined, this.cacheTenant());
1305
1340
  }
1306
1341
  async clearCacheForId(entities) {
1307
- await Promise.all(entities.map((item)=>this.utilsService.clearCache(this.entityName, this.cacheManager, item.id)));
1342
+ await Promise.all(entities.map((item)=>this.utilsService.clearCache(this.entityName, this.cacheManager, item.id, this.cacheTenant())));
1308
1343
  }
1309
1344
  handleError(error) {
1310
1345
  if (error instanceof Error) {
@@ -1312,7 +1347,7 @@ class ApiService {
1312
1347
  }
1313
1348
  throw new common_.InternalServerErrorException({
1314
1349
  message: typeof error === 'string' ? error : 'Unknown error',
1315
- messageKey: message_keys/* .ERROR_MESSAGES.INTERNAL */.UU.INTERNAL
1350
+ messageKey: constants/* .ERROR_MESSAGES.INTERNAL */.UU.INTERNAL
1316
1351
  });
1317
1352
  }
1318
1353
  ensureArray(value) {
@@ -1356,6 +1391,26 @@ class ApiService {
1356
1391
  await qr.release();
1357
1392
  }
1358
1393
  }
1394
+ /**
1395
+ * Client-supplied filter/sort/select keys are interpolated into SQL as column identifiers
1396
+ * (identifiers cannot be bound as parameters), so every key must first be proven to be a
1397
+ * real column property of this entity - anything else is rejected outright.
1398
+ */ assertColumnProperty(key) {
1399
+ if (!this.repository.metadata.findColumnWithPropertyName(key)) {
1400
+ throw new common_.BadRequestException({
1401
+ message: `'${key}' is not a valid field.`,
1402
+ messageKey: constants/* .ERROR_MESSAGES.VALIDATION */.UU.VALIDATION
1403
+ });
1404
+ }
1405
+ }
1406
+ /** Validated `<alias>.<column> = :param` filter with a per-key parameter name, so several
1407
+ * filters in one request no longer overwrite each other's bound value. */ applyEqualsFilter(query, key, value) {
1408
+ this.assertColumnProperty(key);
1409
+ const param = `flt_${key}`;
1410
+ query.andWhere(`${this.entityName}.${key} = :${param}`, {
1411
+ [param]: value
1412
+ });
1413
+ }
1359
1414
  async beforeInsertOperation(_dto, _user, _queryRunner) {}
1360
1415
  async afterInsertOperation(_entity, _dto, _user, _queryRunner) {}
1361
1416
  async beforeUpdateOperation(_dto, _user, _queryRunner) {}
@@ -1363,11 +1418,7 @@ class ApiService {
1363
1418
  async beforeDeleteOperation(_dto, _user, _queryRunner) {}
1364
1419
  async afterDeleteOperation(_entity, _dto, _user, _queryRunner) {}
1365
1420
  async getFilterQuery(query, filter, _user) {
1366
- Object.entries(filter).forEach(([key, value])=>{
1367
- query.andWhere(`${this.entityName}.${key} = :value`, {
1368
- value
1369
- });
1370
- });
1421
+ Object.entries(filter).forEach(([key, value])=>this.applyEqualsFilter(query, key, value));
1371
1422
  return {
1372
1423
  query,
1373
1424
  isRaw: false
@@ -1375,7 +1426,8 @@ class ApiService {
1375
1426
  }
1376
1427
  async getSortQuery(query, sort, _user) {
1377
1428
  Object.entries(sort).forEach(([key, direction])=>{
1378
- query.addOrderBy(`${this.entityName}.${key}`, direction);
1429
+ this.assertColumnProperty(key);
1430
+ query.addOrderBy(`${this.entityName}.${key}`, direction === 'DESC' ? 'DESC' : 'ASC');
1379
1431
  });
1380
1432
  return {
1381
1433
  query,
@@ -1383,7 +1435,10 @@ class ApiService {
1383
1435
  };
1384
1436
  }
1385
1437
  async getSelectQuery(query, _user, select) {
1386
- if (select && select.length) query.select(select.map((field)=>`${this.entityName}.${field}`));
1438
+ if (select && select.length) {
1439
+ select.forEach((field)=>this.assertColumnProperty(field));
1440
+ query.select(select.map((field)=>`${this.entityName}.${field}`));
1441
+ }
1387
1442
  return {
1388
1443
  query,
1389
1444
  isRaw: false
@@ -1419,7 +1474,7 @@ class ApiService {
1419
1474
  });
1420
1475
  if (!existing) throw new common_.NotFoundException({
1421
1476
  message: 'No such entity data found for update! Please, Try Again.',
1422
- messageKey: message_keys/* .ERROR_MESSAGES.NOT_FOUND */.UU.NOT_FOUND
1477
+ messageKey: constants/* .ERROR_MESSAGES.NOT_FOUND */.UU.NOT_FOUND
1423
1478
  });
1424
1479
  return Object.assign(existing, d);
1425
1480
  }
@@ -1559,7 +1614,7 @@ var permissions = __webpack_require__(975);
1559
1614
 
1560
1615
  },
1561
1616
  997(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1562
- /* import */ var _dtos_index_js__rspack_import_0 = __webpack_require__(980);
1617
+ /* import */ var _dtos_index_js__rspack_import_0 = __webpack_require__(746);
1563
1618
  /* import */ var _nestjs_common__rspack_import_1 = __webpack_require__(157);
1564
1619
  /* import */ var _nestjs_swagger__rspack_import_2 = __webpack_require__(176);
1565
1620
 
@@ -1730,7 +1785,7 @@ var constants = __webpack_require__(43);
1730
1785
  946(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1731
1786
  /* import */ var _nestjs_common__rspack_import_0 = __webpack_require__(157);
1732
1787
  /* import */ var _classes_winston_logger_class_js__rspack_import_1 = __webpack_require__(245);
1733
- /* import */ var _middlewares_logger_middleware_js__rspack_import_2 = __webpack_require__(419);
1788
+ /* import */ var _middlewares_logger_middleware_js__rspack_import_2 = __webpack_require__(591);
1734
1789
 
1735
1790
 
1736
1791
 
@@ -2021,53 +2076,6 @@ __webpack_require__.d(__webpack_exports__, {
2021
2076
  });
2022
2077
 
2023
2078
 
2024
- },
2025
- 374(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2026
- /* import */ var _nestjs_common__rspack_import_0 = __webpack_require__(157);
2027
- /* import */ var _constants_message_keys_js__rspack_import_1 = __webpack_require__(389);
2028
-
2029
-
2030
- class PermissionSystemUnavailableException extends _nestjs_common__rspack_import_0.InternalServerErrorException {
2031
- constructor(){
2032
- super({
2033
- success: false,
2034
- message: 'Permission system temporarily unavailable',
2035
- messageKey: _constants_message_keys_js__rspack_import_1/* .ERROR_MESSAGES.PERMISSION_SYSTEM_UNAVAILABLE */.UU.PERMISSION_SYSTEM_UNAVAILABLE
2036
- });
2037
- }
2038
- }
2039
- class InsufficientPermissionsException extends _nestjs_common__rspack_import_0.ForbiddenException {
2040
- constructor(missingPermissions, operator = 'AND'){
2041
- const messageKey = operator === 'OR' ? _constants_message_keys_js__rspack_import_1/* .ERROR_MESSAGES.INSUFFICIENT_PERMISSIONS_OR */.UU.INSUFFICIENT_PERMISSIONS_OR : _constants_message_keys_js__rspack_import_1/* .ERROR_MESSAGES.INSUFFICIENT_PERMISSIONS */.UU.INSUFFICIENT_PERMISSIONS;
2042
- super({
2043
- success: false,
2044
- message: 'Insufficient permissions',
2045
- messageKey,
2046
- messageVariables: {
2047
- permissions: missingPermissions.join(', ')
2048
- },
2049
- missingPermissions,
2050
- operator
2051
- });
2052
- }
2053
- }
2054
- class NoPermissionsFoundException extends _nestjs_common__rspack_import_0.ForbiddenException {
2055
- constructor(){
2056
- super({
2057
- success: false,
2058
- message: 'No permissions found',
2059
- messageKey: _constants_message_keys_js__rspack_import_1/* .ERROR_MESSAGES.NO_PERMISSIONS_FOUND */.UU.NO_PERMISSIONS_FOUND
2060
- });
2061
- }
2062
- }
2063
-
2064
- __webpack_require__.d(__webpack_exports__, {
2065
- GS: () => (PermissionSystemUnavailableException),
2066
- d$: () => (NoPermissionsFoundException),
2067
- z8: () => (InsufficientPermissionsException)
2068
- });
2069
-
2070
-
2071
2079
  },
2072
2080
  510(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2073
2081
 
@@ -2080,8 +2088,8 @@ __webpack_require__.d(__webpack_exports__, {
2080
2088
 
2081
2089
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/constants/index.ts
2082
2090
  var constants = __webpack_require__(43);
2083
- // EXTERNAL MODULE: ./projects/nestjs-shared/src/constants/message-keys.ts
2084
- var message_keys = __webpack_require__(389);
2091
+ // EXTERNAL MODULE: ./projects/nestjs-shared/src/middlewares/logger.middleware.ts + 2 modules
2092
+ var logger_middleware = __webpack_require__(591);
2085
2093
  // EXTERNAL MODULE: external "@nestjs/common"
2086
2094
  var common_ = __webpack_require__(157);
2087
2095
  // EXTERNAL MODULE: external "@nestjs/core"
@@ -2116,6 +2124,7 @@ function _ts_param(paramIndex, decorator) {
2116
2124
 
2117
2125
 
2118
2126
 
2127
+
2119
2128
  class JwtAuthGuard extends (0,__rspack_external__nestjs_passport_18907953.AuthGuard)('jwt') {
2120
2129
  reflector;
2121
2130
  // NOTE: @Inject(Reflector) required for bundled code - external classes need explicit injection
@@ -2137,9 +2146,10 @@ class JwtAuthGuard extends (0,__rspack_external__nestjs_passport_18907953.AuthGu
2137
2146
  if (err || !user) {
2138
2147
  throw err || new common_.UnauthorizedException({
2139
2148
  message: 'Invalid or expired token',
2140
- messageKey: message_keys/* .AUTH_MESSAGES.TOKEN_INVALID */.mK.TOKEN_INVALID
2149
+ messageKey: constants/* .AUTH_MESSAGES.TOKEN_INVALID */.mK.TOKEN_INVALID
2141
2150
  });
2142
2151
  }
2152
+ (0,logger_middleware/* .setRequestUser */.ZV)(user);
2143
2153
  return user;
2144
2154
  }
2145
2155
  }
@@ -2180,6 +2190,7 @@ function optional_jwt_auth_guard_ts_param(paramIndex, decorator) {
2180
2190
 
2181
2191
 
2182
2192
 
2193
+
2183
2194
  class OptionalJwtGuard extends (0,__rspack_external__nestjs_passport_18907953.AuthGuard)('jwt') {
2184
2195
  reflector;
2185
2196
  constructor(reflector){
@@ -2196,6 +2207,7 @@ class OptionalJwtGuard extends (0,__rspack_external__nestjs_passport_18907953.Au
2196
2207
  return super.canActivate(context);
2197
2208
  }
2198
2209
  handleRequest(_err, user) {
2210
+ (0,logger_middleware/* .setRequestUser */.ZV)(user);
2199
2211
  return user || undefined;
2200
2212
  }
2201
2213
  }
@@ -2263,7 +2275,7 @@ class PermissionGuard {
2263
2275
  const user = request.user;
2264
2276
  if (!user) throw new common_.UnauthorizedException({
2265
2277
  message: 'Authentication required',
2266
- messageKey: message_keys/* .AUTH_MESSAGES.TOKEN_REQUIRED */.mK.TOKEN_REQUIRED
2278
+ messageKey: constants/* .AUTH_MESSAGES.TOKEN_REQUIRED */.mK.TOKEN_REQUIRED
2267
2279
  });
2268
2280
  if (!this.permissionCacheService?.isCacheConfigured()) {
2269
2281
  throw new permission_exception/* .PermissionSystemUnavailableException */.GS();
@@ -2449,8 +2461,6 @@ DeleteEmptyIdFromBodyInterceptor = _ts_decorate([
2449
2461
  var hybrid_cache_class = __webpack_require__(375);
2450
2462
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/constants/index.ts
2451
2463
  var constants = __webpack_require__(43);
2452
- // EXTERNAL MODULE: ./projects/nestjs-shared/src/constants/message-keys.ts
2453
- var message_keys = __webpack_require__(389);
2454
2464
  ;// CONCATENATED MODULE: ./projects/nestjs-shared/src/interceptors/idempotency.interceptor.ts
2455
2465
  function idempotency_interceptor_ts_decorate(decorators, target, key, desc) {
2456
2466
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -2507,7 +2517,7 @@ class IdempotencyInterceptor {
2507
2517
  throw new common_.ConflictException({
2508
2518
  success: false,
2509
2519
  message: 'Request is already being processed',
2510
- messageKey: message_keys/* .SYSTEM_MESSAGES.DUPLICATE_REQUEST */.hg.DUPLICATE_REQUEST
2520
+ messageKey: constants/* .SYSTEM_MESSAGES.DUPLICATE_REQUEST */.hg.DUPLICATE_REQUEST
2511
2521
  });
2512
2522
  }
2513
2523
  // Return cached response
@@ -2596,26 +2606,21 @@ function set_user_field_on_body_interceptor_ts_decorate(decorators, target, key,
2596
2606
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2597
2607
  }
2598
2608
 
2599
- /**
2600
- * Factory function to create interceptors that set user ID fields on request body
2601
- * @param fieldName - The field name to set (e.g., 'createdById', 'updatedById', 'deletedById')
2602
- */ function createSetUserFieldInterceptor(fieldName) {
2609
+ /** Stamps `fieldName` on the body from the authenticated user; a client-sent value is always dropped. */ function createSetUserFieldInterceptor(fieldName) {
2603
2610
  let SetUserFieldOnBody = class SetUserFieldOnBody {
2604
2611
  intercept(context, next) {
2605
2612
  const request = context.switchToHttp().getRequest();
2606
- const user = request?.user;
2607
- if (user) {
2608
- if (Array.isArray(request.body)) {
2609
- request.body = request.body.map((item)=>({
2610
- ...item,
2611
- [fieldName]: user.id
2612
- }));
2613
- } else if (typeof request.body === 'object' && request.body !== null) {
2614
- request.body = {
2615
- ...request.body,
2616
- [fieldName]: user.id
2617
- };
2618
- }
2613
+ const userId = request?.user?.id;
2614
+ const stamp = (item)=>{
2615
+ if (typeof item !== 'object' || item === null || Array.isArray(item)) return item;
2616
+ const { [fieldName]: _clientValue, ...rest } = item;
2617
+ return userId ? {
2618
+ ...rest,
2619
+ [fieldName]: userId
2620
+ } : rest;
2621
+ };
2622
+ if (request) {
2623
+ request.body = Array.isArray(request.body) ? request.body.map(stamp) : stamp(request.body);
2619
2624
  }
2620
2625
  return next.handle();
2621
2626
  }
@@ -2625,9 +2630,9 @@ function set_user_field_on_body_interceptor_ts_decorate(decorators, target, key,
2625
2630
  ], SetUserFieldOnBody);
2626
2631
  return SetUserFieldOnBody;
2627
2632
  }
2628
- /** Sets createdById field on request body from authenticated user */ const SetCreatedByOnBody = createSetUserFieldInterceptor('createdById');
2629
- /** Sets updatedById field on request body from authenticated user */ const SetUpdateByOnBody = createSetUserFieldInterceptor('updatedById');
2630
- /** Sets deletedById field on request body from authenticated user */ const SetDeletedByOnBody = createSetUserFieldInterceptor('deletedById');
2633
+ const SetCreatedByOnBody = createSetUserFieldInterceptor('createdById');
2634
+ const SetUpdateByOnBody = createSetUserFieldInterceptor('updatedById');
2635
+ const SetDeletedByOnBody = createSetUserFieldInterceptor('deletedById');
2631
2636
 
2632
2637
  // EXTERNAL MODULE: ./projects/nestjs-shared/src/modules/utils/utils.service.ts
2633
2638
  var utils_service = __webpack_require__(169);
@@ -2703,9 +2708,127 @@ Slug = slug_interceptor_ts_decorate([
2703
2708
 
2704
2709
 
2705
2710
  },
2706
- 823(module) {
2711
+ 928(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2712
+
2713
+ // EXPORTS
2714
+ __webpack_require__.d(__webpack_exports__, {
2715
+ gG: () => (/* reexport */ AUDIT_BODY_KEYS),
2716
+ d0: () => (/* reexport */ DEFAULT_VALIDATION_OPTIONS),
2717
+ zT: () => (/* reexport */ DtoBodyValidationPipe)
2718
+ });
2719
+
2720
+ // EXTERNAL MODULE: external "@nestjs/common"
2721
+ var common_ = __webpack_require__(157);
2722
+ // EXTERNAL MODULE: external "class-validator"
2723
+ var external_class_validator_ = __webpack_require__(421);
2724
+ // EXTERNAL MODULE: ./projects/nestjs-shared/src/constants/message-keys.ts
2725
+ var message_keys = __webpack_require__(389);
2726
+ ;// CONCATENATED MODULE: ./projects/nestjs-shared/src/pipes/dto-body-validation.pipe.ts
2727
+
2728
+
2729
+
2730
+ const DEFAULT_VALIDATION_OPTIONS = {
2731
+ transform: true,
2732
+ whitelist: true,
2733
+ forbidNonWhitelisted: true,
2734
+ transformOptions: {
2735
+ enableImplicitConversion: false
2736
+ }
2737
+ };
2738
+ const AUDIT_BODY_KEYS = [
2739
+ 'createdById',
2740
+ 'updatedById',
2741
+ 'deletedById'
2742
+ ];
2743
+ /**
2744
+ * Validates a generic controller body against its concrete DTO class: a generic
2745
+ * `@Body() dto: T` reflects as `Object`, so the global ValidationPipe skips it.
2746
+ * Audit keys are never taken from the client: `stampedKeys` (written by the endpoint's
2747
+ * SetCreatedByOnBody / SetUpdateByOnBody interceptors, which run first) are kept, any other
2748
+ * audit key is dropped. A `slug` the DTO does not declare is the Slug interceptor's and is kept.
2749
+ */ class DtoBodyValidationPipe {
2750
+ resolveDto;
2751
+ stampedKeys;
2752
+ isArray;
2753
+ options;
2754
+ pipes = new Map();
2755
+ constructor(resolveDto, stampedKeys, isArray = false, options = DEFAULT_VALIDATION_OPTIONS){
2756
+ this.resolveDto = resolveDto;
2757
+ this.stampedKeys = stampedKeys;
2758
+ this.isArray = isArray;
2759
+ this.options = options;
2760
+ }
2761
+ static for(dto, stampedKeys, isArray = false) {
2762
+ return new DtoBodyValidationPipe(()=>dto, stampedKeys, isArray);
2763
+ }
2764
+ async transform(value, metadata) {
2765
+ if (!this.isArray) return this.validateItem(value, metadata);
2766
+ if (!Array.isArray(value)) throw new common_.BadRequestException({
2767
+ message: 'Request body must be an array',
2768
+ messageKey: message_keys/* .ERROR_MESSAGES.VALIDATION */.UU.VALIDATION
2769
+ });
2770
+ return Promise.all(value.map((item)=>this.validateItem(item, metadata)));
2771
+ }
2772
+ async validateItem(item, metadata) {
2773
+ if (item === null || typeof item !== 'object' || Array.isArray(item)) {
2774
+ throw new common_.BadRequestException({
2775
+ message: 'Request body item must be an object',
2776
+ messageKey: message_keys/* .ERROR_MESSAGES.VALIDATION */.UU.VALIDATION
2777
+ });
2778
+ }
2779
+ const dto = this.resolveDto(item);
2780
+ const rest = {
2781
+ ...item
2782
+ };
2783
+ const injected = {};
2784
+ for (const key of AUDIT_BODY_KEYS){
2785
+ if (!(key in rest)) continue;
2786
+ if (this.stampedKeys.includes(key)) injected[key] = rest[key];
2787
+ delete rest[key];
2788
+ }
2789
+ if ('slug' in rest && !declaresProperty(dto, 'slug')) {
2790
+ injected['slug'] = rest['slug'];
2791
+ delete rest['slug'];
2792
+ }
2793
+ const validated = await this.pipeFor(dto).transform(rest, {
2794
+ ...metadata,
2795
+ metatype: dto
2796
+ });
2797
+ return Object.assign(validated, injected);
2798
+ }
2799
+ pipeFor(dto) {
2800
+ let pipe = this.pipes.get(dto);
2801
+ if (!pipe) {
2802
+ pipe = new common_.ValidationPipe({
2803
+ ...this.options,
2804
+ expectedType: dto
2805
+ });
2806
+ this.pipes.set(dto, pipe);
2807
+ }
2808
+ return pipe;
2809
+ }
2810
+ }
2811
+ function declaresProperty(dto, key) {
2812
+ return (0,external_class_validator_.getMetadataStorage)().getTargetValidationMetadatas(dto, '', true, false).some((m)=>m.propertyName === key);
2813
+ }
2814
+
2815
+ ;// CONCATENATED MODULE: ./projects/nestjs-shared/src/pipes/index.ts
2816
+
2817
+
2818
+
2819
+ },
2820
+ 154(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2821
+ /**
2822
+ * The tenant a cache key belongs to: the provider's current tenant in multi-tenant mode, else
2823
+ * undefined. A single database never prefixes, so a stray tenant header cannot split its cache.
2824
+ */ function cacheTenantId(provider) {
2825
+ if (!provider?.isMultiTenant?.()) return undefined;
2826
+ return provider.getCurrentTenantId?.() ?? undefined;
2827
+ }
2707
2828
 
2708
- module.exports = __rspack_external_crypto;
2829
+ __webpack_require__.d(__webpack_exports__, {
2830
+ q: () => (cacheTenantId)
2831
+ });
2709
2832
 
2710
2833
 
2711
2834
  },