@flusys/nestjs-shared 4.1.0 → 5.0.0

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 (60) hide show
  1. package/README.md +96 -606
  2. package/cjs/classes/api-controller.class.js +81 -10
  3. package/cjs/classes/api-service.class.js +9 -7
  4. package/cjs/classes/index.js +0 -1
  5. package/cjs/constants/index.js +0 -4
  6. package/cjs/constants/message-keys.js +3 -21
  7. package/cjs/constants/permissions.js +0 -10
  8. package/cjs/decorators/api-response.decorator.js +1 -2
  9. package/cjs/decorators/index.js +0 -1
  10. package/cjs/decorators/require-permission.decorator.js +0 -4
  11. package/cjs/exceptions/base-app.exception.js +4 -4
  12. package/cjs/exceptions/permission.exception.js +1 -1
  13. package/cjs/filters/global-exception.filter.js +4 -4
  14. package/cjs/interfaces/index.js +0 -1
  15. package/cjs/modules/datasource/multi-tenant-datasource.service.js +2 -2
  16. package/cjs/utils/date-time.util.js +94 -0
  17. package/cjs/utils/index.js +1 -0
  18. package/cjs/utils/query-helpers.util.js +2 -2
  19. package/cjs/utils/request.util.js +25 -0
  20. package/classes/index.d.ts +0 -1
  21. package/constants/index.d.ts +0 -1
  22. package/constants/message-keys.d.ts +2 -44
  23. package/constants/permissions.d.ts +0 -12
  24. package/decorators/api-response.decorator.d.ts +1 -1
  25. package/decorators/index.d.ts +0 -1
  26. package/decorators/require-permission.decorator.d.ts +0 -1
  27. package/exceptions/base-app.exception.d.ts +2 -2
  28. package/fesm/classes/api-controller.class.js +82 -11
  29. package/fesm/classes/api-service.class.js +10 -8
  30. package/fesm/classes/index.js +0 -1
  31. package/fesm/constants/index.js +0 -1
  32. package/fesm/constants/message-keys.js +3 -19
  33. package/fesm/constants/permissions.js +0 -7
  34. package/fesm/decorators/api-response.decorator.js +2 -20
  35. package/fesm/decorators/index.js +0 -1
  36. package/fesm/decorators/require-permission.decorator.js +0 -1
  37. package/fesm/exceptions/base-app.exception.js +4 -4
  38. package/fesm/exceptions/permission.exception.js +1 -1
  39. package/fesm/filters/global-exception.filter.js +4 -4
  40. package/fesm/interfaces/index.js +0 -1
  41. package/fesm/modules/datasource/multi-tenant-datasource.service.js +2 -2
  42. package/fesm/utils/date-time.util.js +70 -0
  43. package/fesm/utils/index.js +1 -0
  44. package/fesm/utils/query-helpers.util.js +2 -2
  45. package/fesm/utils/request.util.js +22 -0
  46. package/interfaces/event-manager-adapter.interface.d.ts +12 -12
  47. package/interfaces/index.d.ts +0 -1
  48. package/package.json +2 -2
  49. package/utils/date-time.util.d.ts +8 -0
  50. package/utils/index.d.ts +1 -0
  51. package/utils/request.util.d.ts +2 -0
  52. package/cjs/classes/winston-logger-adapter.class.js +0 -99
  53. package/cjs/decorators/sanitize-html.decorator.js +0 -36
  54. package/cjs/interfaces/logger.interface.js +0 -4
  55. package/classes/winston-logger-adapter.class.d.ts +0 -23
  56. package/decorators/sanitize-html.decorator.d.ts +0 -2
  57. package/fesm/classes/winston-logger-adapter.class.js +0 -81
  58. package/fesm/decorators/sanitize-html.decorator.js +0 -45
  59. package/fesm/interfaces/logger.interface.js +0 -1
  60. package/interfaces/logger.interface.d.ts +0 -7
@@ -1,7 +1,7 @@
1
1
  export declare const AUTH_MESSAGES: {
2
2
  readonly TOKEN_REQUIRED: "auth.token.required";
3
3
  readonly TOKEN_INVALID: "auth.token.invalid";
4
- readonly TOKEN_EXPIRED: "auth.token.expired";
4
+ readonly ENTITY_BELOG_ANOTHER_COMPANY: "entity.belongs.another.company";
5
5
  readonly COMPANY_NO_ACCESS: "auth.company.no.access";
6
6
  };
7
7
  export declare const ERROR_MESSAGES: {
@@ -19,6 +19,7 @@ export declare const ERROR_MESSAGES: {
19
19
  readonly INSUFFICIENT_PERMISSIONS: "error.insufficient.permissions";
20
20
  readonly INSUFFICIENT_PERMISSIONS_OR: "error.insufficient.permissions.or";
21
21
  readonly NO_PERMISSIONS_FOUND: "error.no.permissions.found";
22
+ readonly ENDPOINT_DISABLED: "error.endpoint.disabled";
22
23
  };
23
24
  export declare const SYSTEM_MESSAGES: {
24
25
  readonly REPOSITORY_NOT_AVAILABLE: "system.repository.not.available";
@@ -27,7 +28,6 @@ export declare const SYSTEM_MESSAGES: {
27
28
  readonly SERVICE_NOT_AVAILABLE: "system.service.not.available";
28
29
  readonly CONFIG_REQUIRED: "system.config.required";
29
30
  readonly INTERNAL_ERROR: "system.internal.error";
30
- readonly NOT_FOUND: "system.not.found";
31
31
  readonly DUPLICATE_REQUEST: "system.duplicate.request";
32
32
  readonly INVALID_TENANT_ID: "system.invalid.tenant.id";
33
33
  readonly TENANT_NOT_FOUND: "system.tenant.not.found";
@@ -37,45 +37,3 @@ export declare const SYSTEM_MESSAGES: {
37
37
  readonly PATH_TRAVERSAL_DETECTED: "system.path.traversal.detected";
38
38
  readonly INVALID_FILE_KEY: "system.invalid.file.key";
39
39
  };
40
- export declare const MESSAGE_KEYS: {
41
- readonly AUTH: {
42
- readonly TOKEN_REQUIRED: "auth.token.required";
43
- readonly TOKEN_INVALID: "auth.token.invalid";
44
- readonly TOKEN_EXPIRED: "auth.token.expired";
45
- readonly COMPANY_NO_ACCESS: "auth.company.no.access";
46
- };
47
- readonly ERROR: {
48
- readonly NOT_FOUND: "error.not.found";
49
- readonly VALIDATION: "error.validation";
50
- readonly UNAUTHORIZED: "error.unauthorized";
51
- readonly FORBIDDEN: "error.forbidden";
52
- readonly CONFLICT: "error.conflict";
53
- readonly INTERNAL: "error.internal";
54
- readonly SERVICE_UNAVAILABLE: "error.service.unavailable";
55
- readonly UNKNOWN: "error.unknown";
56
- readonly HTTP: "error.http";
57
- readonly GENERIC: "error.generic";
58
- readonly PERMISSION_SYSTEM_UNAVAILABLE: "error.permission.system.unavailable";
59
- readonly INSUFFICIENT_PERMISSIONS: "error.insufficient.permissions";
60
- readonly INSUFFICIENT_PERMISSIONS_OR: "error.insufficient.permissions.or";
61
- readonly NO_PERMISSIONS_FOUND: "error.no.permissions.found";
62
- };
63
- readonly SYSTEM: {
64
- readonly REPOSITORY_NOT_AVAILABLE: "system.repository.not.available";
65
- readonly DATASOURCE_NOT_AVAILABLE: "system.datasource.not.available";
66
- readonly DATABASE_CONFIG_NOT_AVAILABLE: "system.database.config.not.available";
67
- readonly SERVICE_NOT_AVAILABLE: "system.service.not.available";
68
- readonly CONFIG_REQUIRED: "system.config.required";
69
- readonly INTERNAL_ERROR: "system.internal.error";
70
- readonly NOT_FOUND: "system.not.found";
71
- readonly DUPLICATE_REQUEST: "system.duplicate.request";
72
- readonly INVALID_TENANT_ID: "system.invalid.tenant.id";
73
- readonly TENANT_NOT_FOUND: "system.tenant.not.found";
74
- readonly TENANT_HEADER_REQUIRED: "system.tenant.header.required";
75
- readonly MISSING_PARAMETER: "system.missing.parameter";
76
- readonly SDK_NOT_INSTALLED: "system.sdk.not.installed";
77
- readonly PATH_TRAVERSAL_DETECTED: "system.path.traversal.detected";
78
- readonly INVALID_FILE_KEY: "system.invalid.file.key";
79
- };
80
- };
81
- export type MessageKey = (typeof MESSAGE_KEYS)[keyof typeof MESSAGE_KEYS][keyof (typeof MESSAGE_KEYS)[keyof typeof MESSAGE_KEYS]];
@@ -92,12 +92,6 @@ export declare const EVENT_PERMISSIONS: {
92
92
  readonly UPDATE: "event.update";
93
93
  readonly DELETE: "event.delete";
94
94
  };
95
- export declare const EVENT_PARTICIPANT_PERMISSIONS: {
96
- readonly CREATE: "event-participant.create";
97
- readonly READ: "event-participant.read";
98
- readonly UPDATE: "event-participant.update";
99
- readonly DELETE: "event-participant.delete";
100
- };
101
95
  export declare const NOTIFICATION_PERMISSIONS: {
102
96
  readonly CREATE: "notification.create";
103
97
  readonly READ: "notification.read";
@@ -217,12 +211,6 @@ export declare const PERMISSIONS: {
217
211
  readonly UPDATE: "event.update";
218
212
  readonly DELETE: "event.delete";
219
213
  };
220
- readonly EVENT_PARTICIPANT: {
221
- readonly CREATE: "event-participant.create";
222
- readonly READ: "event-participant.read";
223
- readonly UPDATE: "event-participant.update";
224
- readonly DELETE: "event-participant.delete";
225
- };
226
214
  readonly NOTIFICATION: {
227
215
  readonly CREATE: "notification.create";
228
216
  readonly READ: "notification.read";
@@ -1,3 +1,3 @@
1
1
  import { Type } from '@nestjs/common';
2
- export type ArrayResponseType = 'list' | 'bulk';
2
+ export type ArrayResponseType = 'list' | 'bulk' | 'single';
3
3
  export declare const ApiResponseDto: <T extends Type<unknown>>(dto: T, isArray?: boolean, arrayType?: ArrayResponseType) => <TFunction extends Function, Y>(target: TFunction | object, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
@@ -3,4 +3,3 @@ export * from './current-user.decorator';
3
3
  export * from './log-action.decorator';
4
4
  export * from './public.decorator';
5
5
  export * from './require-permission.decorator';
6
- export * from './sanitize-html.decorator';
@@ -2,4 +2,3 @@ import { IPermissionLogic } from '../interfaces/permission.interface';
2
2
  export declare const RequirePermission: (...permissions: string[]) => import("@nestjs/common").CustomDecorator<string>;
3
3
  export declare const RequireAnyPermission: (...permissions: string[]) => import("@nestjs/common").CustomDecorator<string>;
4
4
  export declare const RequirePermissionLogic: (logic: IPermissionLogic) => import("@nestjs/common").CustomDecorator<string>;
5
- export declare const RequirePermissionCondition: (logic: IPermissionLogic) => import("@nestjs/common").CustomDecorator<string>;
@@ -6,14 +6,14 @@ export interface IValidationError {
6
6
  export interface IBaseAppExceptionOptions {
7
7
  message: string;
8
8
  messageKey?: string;
9
- messageParams?: Record<string, unknown>;
9
+ messageVariables?: Record<string, unknown>;
10
10
  status?: HttpStatus;
11
11
  errors?: IValidationError[];
12
12
  metadata?: Record<string, unknown>;
13
13
  }
14
14
  export declare class BaseAppException extends HttpException {
15
15
  readonly messageKey: string;
16
- readonly messageParams?: Record<string, unknown>;
16
+ readonly messageVariables?: Record<string, unknown>;
17
17
  readonly errors?: IValidationError[];
18
18
  readonly metadata?: Record<string, unknown>;
19
19
  constructor(options: IBaseAppExceptionOptions);
@@ -31,7 +31,8 @@ import { plainToInstance } from 'class-transformer';
31
31
  import { CurrentUser, Public, RequireAnyPermission, RequirePermission, RequirePermissionLogic } from '../decorators';
32
32
  import { ApiResponseDto } from '../decorators/api-response.decorator';
33
33
  import { DeleteDto, FilterAndPaginationDto, GetByIdBodyDto, GetByIdsDto } from '../dtos';
34
- import { ForbiddenException, NotFoundException } from '../exceptions';
34
+ import { BaseAppException, NotFoundException } from '../exceptions';
35
+ import { ERROR_MESSAGES } from '../constants/message-keys';
35
36
  import { JwtAuthGuard, PermissionGuard } from '../guards';
36
37
  import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpdateByOnBody, Slug } from '../interceptors';
37
38
  /**
@@ -142,7 +143,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
142
143
  }
143
144
  async insert(addDto, user) {
144
145
  if (!this.isEnabled('insert')) {
145
- throw new ForbiddenException(`Endpoint 'insert' is disabled`);
146
+ throw new BaseAppException({
147
+ message: `Endpoint 'insert' is disabled`,
148
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
149
+ messageVariables: {
150
+ endpoint: 'insert'
151
+ },
152
+ status: HttpStatus.FORBIDDEN
153
+ });
146
154
  }
147
155
  const entity = await this.service.insert(addDto, user);
148
156
  const data = plainToInstance(responseDtoClass, entity);
@@ -155,7 +163,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
155
163
  }
156
164
  async insertMany(addDto, user) {
157
165
  if (!this.isEnabled('insertMany')) {
158
- throw new ForbiddenException(`Endpoint 'insertMany' is disabled`);
166
+ throw new BaseAppException({
167
+ message: `Endpoint 'insertMany' is disabled`,
168
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
169
+ messageVariables: {
170
+ endpoint: 'insertMany'
171
+ },
172
+ status: HttpStatus.FORBIDDEN
173
+ });
159
174
  }
160
175
  const entities = await this.service.insertMany(addDto, user);
161
176
  const data = entities.map((item)=>plainToInstance(responseDtoClass, item));
@@ -176,7 +191,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
176
191
  }
177
192
  async getById(id, body, user) {
178
193
  if (!this.isEnabled('getById')) {
179
- throw new ForbiddenException(`Endpoint 'getById' is disabled`);
194
+ throw new BaseAppException({
195
+ message: `Endpoint 'getById' is disabled`,
196
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
197
+ messageVariables: {
198
+ endpoint: 'getById'
199
+ },
200
+ status: HttpStatus.FORBIDDEN
201
+ });
180
202
  }
181
203
  const entity = await this.service.findById(id, user, body?.select);
182
204
  const data = plainToInstance(responseDtoClass, entity);
@@ -189,7 +211,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
189
211
  }
190
212
  async getByIds(body, user) {
191
213
  if (!this.isEnabled('getByIds')) {
192
- throw new ForbiddenException(`Endpoint 'getByIds' is disabled`);
214
+ throw new BaseAppException({
215
+ message: `Endpoint 'getByIds' is disabled`,
216
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
217
+ messageVariables: {
218
+ endpoint: 'getByIds'
219
+ },
220
+ status: HttpStatus.FORBIDDEN
221
+ });
193
222
  }
194
223
  const entities = await this.service.findByIds(body.ids, user, body?.select);
195
224
  const data = plainToInstance(responseDtoClass, entities);
@@ -209,7 +238,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
209
238
  }
210
239
  async update(updateDto, user) {
211
240
  if (!this.isEnabled('update')) {
212
- throw new ForbiddenException(`Endpoint 'update' is disabled`);
241
+ throw new BaseAppException({
242
+ message: `Endpoint 'update' is disabled`,
243
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
244
+ messageVariables: {
245
+ endpoint: 'update'
246
+ },
247
+ status: HttpStatus.FORBIDDEN
248
+ });
213
249
  }
214
250
  const entity = await this.service.update(updateDto, user);
215
251
  const data = plainToInstance(responseDtoClass, entity);
@@ -222,7 +258,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
222
258
  }
223
259
  async updateMany(updateDtos, user) {
224
260
  if (!this.isEnabled('updateMany')) {
225
- throw new ForbiddenException(`Endpoint 'updateMany' is disabled`);
261
+ throw new BaseAppException({
262
+ message: `Endpoint 'updateMany' is disabled`,
263
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
264
+ messageVariables: {
265
+ endpoint: 'updateMany'
266
+ },
267
+ status: HttpStatus.FORBIDDEN
268
+ });
226
269
  }
227
270
  const entities = await this.service.updateMany(updateDtos, user);
228
271
  const data = plainToInstance(responseDtoClass, entities);
@@ -243,7 +286,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
243
286
  }
244
287
  async bulkUpsert(dtos, user) {
245
288
  if (!this.isEnabled('bulkUpsert')) {
246
- throw new ForbiddenException(`Endpoint 'bulkUpsert' is disabled`);
289
+ throw new BaseAppException({
290
+ message: `Endpoint 'bulkUpsert' is disabled`,
291
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
292
+ messageVariables: {
293
+ endpoint: 'bulkUpsert'
294
+ },
295
+ status: HttpStatus.FORBIDDEN
296
+ });
247
297
  }
248
298
  const toInsert = [];
249
299
  const toUpdate = [];
@@ -273,7 +323,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
273
323
  }
274
324
  async getByFilter(filter, user) {
275
325
  if (!this.isEnabled('getByFilter')) {
276
- throw new ForbiddenException(`Endpoint 'getByFilter' is disabled`);
326
+ throw new BaseAppException({
327
+ message: `Endpoint 'getByFilter' is disabled`,
328
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
329
+ messageVariables: {
330
+ endpoint: 'getByFilter'
331
+ },
332
+ status: HttpStatus.FORBIDDEN
333
+ });
277
334
  }
278
335
  const result = await this.service.getAll('', {
279
336
  filter,
@@ -296,7 +353,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
296
353
  }
297
354
  async getAll(filterAndPaginationDto, user, search) {
298
355
  if (!this.isEnabled('getAll')) {
299
- throw new ForbiddenException(`Endpoint 'getAll' is disabled`);
356
+ throw new BaseAppException({
357
+ message: `Endpoint 'getAll' is disabled`,
358
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
359
+ messageVariables: {
360
+ endpoint: 'getAll'
361
+ },
362
+ status: HttpStatus.FORBIDDEN
363
+ });
300
364
  }
301
365
  const result = await this.service.getAll(search ?? '', filterAndPaginationDto, user);
302
366
  const data = plainToInstance(responseDtoClass, result.data);
@@ -320,7 +384,14 @@ import { IdempotencyInterceptor, SetCreatedByOnBody, SetDeletedByOnBody, SetUpda
320
384
  }
321
385
  async delete(deleteDto, user) {
322
386
  if (!this.isEnabled('delete')) {
323
- throw new ForbiddenException(`Endpoint 'delete' is disabled`);
387
+ throw new BaseAppException({
388
+ message: `Endpoint 'delete' is disabled`,
389
+ messageKey: ERROR_MESSAGES.ENDPOINT_DISABLED,
390
+ messageVariables: {
391
+ endpoint: 'delete'
392
+ },
393
+ status: HttpStatus.FORBIDDEN
394
+ });
324
395
  }
325
396
  await this.service.delete(deleteDto, user);
326
397
  const count = Array.isArray(deleteDto.id) ? deleteDto.id.length : 1;
@@ -22,7 +22,7 @@ function _ts_metadata(k, v) {
22
22
  }
23
23
  import { InternalServerErrorException, NotFoundException } from '@nestjs/common';
24
24
  import { In } from 'typeorm';
25
- import { SYSTEM_MESSAGES } from '../constants';
25
+ import { ERROR_MESSAGES, SYSTEM_MESSAGES } from '../constants';
26
26
  import { LogAction } from '../decorators/log-action.decorator';
27
27
  import { DeleteDto } from '../dtos';
28
28
  /** Generic API service with CRUD operations and caching support */ export class ApiService {
@@ -115,7 +115,7 @@ import { DeleteDto } from '../dtos';
115
115
  const result = this.convertEntityListToResponseListDto(output, isRaw);
116
116
  if (!result || !result.length) throw new NotFoundException({
117
117
  message: 'No Data Found',
118
- messageKey: SYSTEM_MESSAGES.NOT_FOUND
118
+ messageKey: ERROR_MESSAGES.NOT_FOUND
119
119
  });
120
120
  return result;
121
121
  } catch (error) {
@@ -149,7 +149,7 @@ import { DeleteDto } from '../dtos';
149
149
  output = await finalQuery.getOne();
150
150
  if (!output) throw new NotFoundException({
151
151
  message: 'No Data Found',
152
- messageKey: SYSTEM_MESSAGES.NOT_FOUND
152
+ messageKey: ERROR_MESSAGES.NOT_FOUND
153
153
  });
154
154
  result = this.convertEntityToResponseDto(output, false);
155
155
  }
@@ -239,18 +239,20 @@ import { DeleteDto } from '../dtos';
239
239
  `;
240
240
  const parameters = rawSubQuery.getParameters();
241
241
  const orderedValues = [];
242
+ const isPostgres = this.repository.manager.connection.options.type === 'postgres';
243
+ let paramIndex = 0;
242
244
  const convertedQuery = countSql.replace(/:(\w+)/g, (_, key)=>{
243
245
  if (!(key in parameters)) {
244
246
  throw new InternalServerErrorException({
245
247
  message: `Missing parameter value for: ${key}`,
246
248
  messageKey: SYSTEM_MESSAGES.MISSING_PARAMETER,
247
- messageParams: {
249
+ messageVariables: {
248
250
  key
249
251
  }
250
252
  });
251
253
  }
252
254
  orderedValues.push(parameters[key]);
253
- return '?';
255
+ return isPostgres ? `$${++paramIndex}` : '?';
254
256
  });
255
257
  const result = await this.repository.query(convertedQuery, orderedValues);
256
258
  total = Number(result[0]?.count || 0);
@@ -327,7 +329,7 @@ import { DeleteDto } from '../dtos';
327
329
  }
328
330
  throw new InternalServerErrorException({
329
331
  message: typeof error === 'string' ? error : 'Unknown error',
330
- messageKey: SYSTEM_MESSAGES.INTERNAL_ERROR
332
+ messageKey: ERROR_MESSAGES.INTERNAL
331
333
  });
332
334
  }
333
335
  /** Ensures value is always an array */ ensureArray(value) {
@@ -427,7 +429,7 @@ import { DeleteDto } from '../dtos';
427
429
  });
428
430
  if (!existing) throw new NotFoundException({
429
431
  message: 'No such entity data found for update! Please, Try Again.',
430
- messageKey: SYSTEM_MESSAGES.NOT_FOUND
432
+ messageKey: ERROR_MESSAGES.NOT_FOUND
431
433
  });
432
434
  return Object.assign(existing, d);
433
435
  }
@@ -441,7 +443,7 @@ import { DeleteDto } from '../dtos';
441
443
  return Object.assign({}, entity);
442
444
  }
443
445
  convertEntityListToResponseListDto(entities, _isRaw) {
444
- return entities.map((entity)=>Object.assign({}, entity));
446
+ return entities.map((entity)=>this.convertEntityToResponseDto(entity, _isRaw));
445
447
  }
446
448
  async getEntityClass() {
447
449
  return await this.repository.create();
@@ -2,7 +2,6 @@ export * from './api-controller.class';
2
2
  export * from './api-service.class';
3
3
  export * from './request-scoped-api.service';
4
4
  export * from './hybrid-cache.class';
5
- export * from './winston-logger-adapter.class';
6
5
  export * from './winston.logger.class';
7
6
  // Re-export permission constants for convenience
8
7
  export * from '../constants/permissions';
@@ -4,7 +4,6 @@ export const PERMISSIONS_KEY = 'permissions';
4
4
  // Injection tokens
5
5
  export const CACHE_INSTANCE = 'CACHE_INSTANCE';
6
6
  export const PERMISSION_GUARD_CONFIG = 'PERMISSION_GUARD_CONFIG';
7
- export const LOGGER_INSTANCE = 'LOGGER_INSTANCE';
8
7
  // Header names
9
8
  export const IDEMPOTENCY_KEY_HEADER = 'x-idempotency-key';
10
9
  export const REQUEST_ID_HEADER = 'x-request-id';
@@ -1,19 +1,9 @@
1
- // ==================== SHARED/SYSTEM MESSAGE KEYS ====================
2
- // Package-specific messages are now in their respective packages:
3
- // - nestjs-auth/src/config/message-keys.ts
4
- // - nestjs-iam/src/config/message-keys.ts
5
- // - nestjs-storage/src/config/message-keys.ts
6
- // - nestjs-email/src/config/message-keys.ts
7
- // - nestjs-form-builder/src/config/message-keys.ts
8
- // - nestjs-event-manager/src/config/message-keys.ts
9
- // - nestjs-notification/src/config/message-keys.ts
10
- // - nestjs-localization/src/config/message-keys.ts
11
1
  // ==================== AUTH (Shared across guards/interceptors) ====================
12
2
  // These are duplicated in nestjs-auth but needed here to avoid circular dependencies
13
3
  export const AUTH_MESSAGES = {
14
4
  TOKEN_REQUIRED: 'auth.token.required',
15
5
  TOKEN_INVALID: 'auth.token.invalid',
16
- TOKEN_EXPIRED: 'auth.token.expired',
6
+ ENTITY_BELOG_ANOTHER_COMPANY: 'entity.belongs.another.company',
17
7
  COMPANY_NO_ACCESS: 'auth.company.no.access'
18
8
  };
19
9
  // ==================== ERROR (HTTP Exceptions) ====================
@@ -31,7 +21,8 @@ export const ERROR_MESSAGES = {
31
21
  PERMISSION_SYSTEM_UNAVAILABLE: 'error.permission.system.unavailable',
32
22
  INSUFFICIENT_PERMISSIONS: 'error.insufficient.permissions',
33
23
  INSUFFICIENT_PERMISSIONS_OR: 'error.insufficient.permissions.or',
34
- NO_PERMISSIONS_FOUND: 'error.no.permissions.found'
24
+ NO_PERMISSIONS_FOUND: 'error.no.permissions.found',
25
+ ENDPOINT_DISABLED: 'error.endpoint.disabled'
35
26
  };
36
27
  // ==================== SYSTEM (Infrastructure) ====================
37
28
  export const SYSTEM_MESSAGES = {
@@ -41,7 +32,6 @@ export const SYSTEM_MESSAGES = {
41
32
  SERVICE_NOT_AVAILABLE: 'system.service.not.available',
42
33
  CONFIG_REQUIRED: 'system.config.required',
43
34
  INTERNAL_ERROR: 'system.internal.error',
44
- NOT_FOUND: 'system.not.found',
45
35
  DUPLICATE_REQUEST: 'system.duplicate.request',
46
36
  INVALID_TENANT_ID: 'system.invalid.tenant.id',
47
37
  TENANT_NOT_FOUND: 'system.tenant.not.found',
@@ -51,9 +41,3 @@ export const SYSTEM_MESSAGES = {
51
41
  PATH_TRAVERSAL_DETECTED: 'system.path.traversal.detected',
52
42
  INVALID_FILE_KEY: 'system.invalid.file.key'
53
43
  };
54
- // ==================== AGGREGATED EXPORTS ====================
55
- export const MESSAGE_KEYS = {
56
- AUTH: AUTH_MESSAGES,
57
- ERROR: ERROR_MESSAGES,
58
- SYSTEM: SYSTEM_MESSAGES
59
- };
@@ -98,12 +98,6 @@ export const EVENT_PERMISSIONS = {
98
98
  UPDATE: 'event.update',
99
99
  DELETE: 'event.delete'
100
100
  };
101
- export const EVENT_PARTICIPANT_PERMISSIONS = {
102
- CREATE: 'event-participant.create',
103
- READ: 'event-participant.read',
104
- UPDATE: 'event-participant.update',
105
- DELETE: 'event-participant.delete'
106
- };
107
101
  // ==================== NOTIFICATION MODULE ====================
108
102
  export const NOTIFICATION_PERMISSIONS = {
109
103
  CREATE: 'notification.create',
@@ -155,7 +149,6 @@ export const PERMISSIONS = {
155
149
  FORM_RESULT: FORM_RESULT_PERMISSIONS,
156
150
  // Event Manager
157
151
  EVENT: EVENT_PERMISSIONS,
158
- EVENT_PARTICIPANT: EVENT_PARTICIPANT_PERMISSIONS,
159
152
  // Notification
160
153
  NOTIFICATION: NOTIFICATION_PERMISSIONS,
161
154
  // Localization
@@ -1,28 +1,10 @@
1
1
  import { BulkMetaDto, BulkResponseDto, ListResponseDto, PaginationMetaDto, SingleResponseDto } from '../dtos';
2
2
  import { applyDecorators } from '@nestjs/common';
3
3
  import { ApiExtraModels, ApiOkResponse, getSchemaPath } from '@nestjs/swagger';
4
- /**
5
- * API Response Decorator
6
- * Wraps response with the appropriate response structure
7
- *
8
- * @param dto - The DTO class for the data
9
- * @param isArray - Whether the data is an array (default: false)
10
- * @param arrayType - For arrays: 'list' (paginated) or 'bulk' (operations) (default: 'list')
11
- *
12
- * @example
13
- * // Single item response
14
- * @ApiResponseDto(UserDto)
15
- *
16
- * // Paginated list response (get-all)
17
- * @ApiResponseDto(UserDto, true, 'list')
18
- *
19
- * // Bulk operation response (insert-many, update-many)
20
- * @ApiResponseDto(UserDto, true, 'bulk')
21
- */ export const ApiResponseDto = (dto, isArray = false, arrayType = 'list')=>{
22
- // Select appropriate wrapper based on response type
4
+ export const ApiResponseDto = (dto, isArray = false, arrayType = 'list')=>{
23
5
  let wrapperDto;
24
6
  let metaDto = null;
25
- if (!isArray) {
7
+ if (!isArray || arrayType === 'single') {
26
8
  wrapperDto = SingleResponseDto;
27
9
  } else if (arrayType === 'bulk') {
28
10
  wrapperDto = BulkResponseDto;
@@ -3,4 +3,3 @@ export * from './current-user.decorator';
3
3
  export * from './log-action.decorator';
4
4
  export * from './public.decorator';
5
5
  export * from './require-permission.decorator';
6
- export * from './sanitize-html.decorator';
@@ -25,4 +25,3 @@ import { PERMISSIONS_KEY } from '../constants';
25
25
  * ],
26
26
  * })
27
27
  */ export const RequirePermissionLogic = (logic)=>SetMetadata(PERMISSIONS_KEY, logic);
28
- /** @deprecated Use RequirePermissionLogic instead */ export const RequirePermissionCondition = RequirePermissionLogic;
@@ -20,11 +20,11 @@ export class BaseAppException extends HttpException {
20
20
  success: false,
21
21
  message: options.message,
22
22
  messageKey: options.messageKey || ERROR_MESSAGES.GENERIC,
23
- messageParams: options.messageParams,
23
+ messageVariables: options.messageVariables,
24
24
  errors: options.errors
25
- }, status), _define_property(this, "messageKey", void 0), _define_property(this, "messageParams", void 0), _define_property(this, "errors", void 0), _define_property(this, "metadata", void 0);
25
+ }, status), _define_property(this, "messageKey", void 0), _define_property(this, "messageVariables", void 0), _define_property(this, "errors", void 0), _define_property(this, "metadata", void 0);
26
26
  this.messageKey = options.messageKey || ERROR_MESSAGES.GENERIC;
27
- this.messageParams = options.messageParams;
27
+ this.messageVariables = options.messageVariables;
28
28
  this.errors = options.errors;
29
29
  this.metadata = options.metadata;
30
30
  }
@@ -97,7 +97,7 @@ export class ServiceUnavailableException extends BaseAppException {
97
97
  super({
98
98
  message: `${service} is temporarily unavailable`,
99
99
  messageKey: ERROR_MESSAGES.SERVICE_UNAVAILABLE,
100
- messageParams: {
100
+ messageVariables: {
101
101
  service
102
102
  },
103
103
  status: HttpStatus.SERVICE_UNAVAILABLE,
@@ -16,7 +16,7 @@ export class InsufficientPermissionsException extends ForbiddenException {
16
16
  success: false,
17
17
  message: 'Insufficient permissions',
18
18
  messageKey,
19
- messageParams: {
19
+ messageVariables: {
20
20
  permissions: missingPermissions.join(', ')
21
21
  },
22
22
  missingPermissions,
@@ -61,7 +61,7 @@ export class GlobalExceptionFilter {
61
61
  success: false,
62
62
  message: exception.message,
63
63
  messageKey: exception.messageKey,
64
- messageParams: exception.messageParams,
64
+ messageVariables: exception.messageVariables,
65
65
  errors: exception.errors,
66
66
  _meta: {
67
67
  requestId,
@@ -72,12 +72,12 @@ export class GlobalExceptionFilter {
72
72
  }
73
73
  if (exception instanceof HttpException) {
74
74
  const response = exception.getResponse();
75
- const { message, messageKey, messageParams, errors } = this.extractHttpExceptionDetails(response);
75
+ const { message, messageKey, messageVariables, errors } = this.extractHttpExceptionDetails(response);
76
76
  return {
77
77
  success: false,
78
78
  message,
79
79
  messageKey,
80
- messageParams,
80
+ messageVariables,
81
81
  errors,
82
82
  _meta: {
83
83
  requestId,
@@ -124,7 +124,7 @@ export class GlobalExceptionFilter {
124
124
  return {
125
125
  message: String(obj.message || 'Unknown error'),
126
126
  messageKey: String(obj.messageKey || ERROR_MESSAGES.HTTP),
127
- messageParams: obj.messageParams,
127
+ messageVariables: obj.messageVariables,
128
128
  errors: obj.errors
129
129
  };
130
130
  }
@@ -3,7 +3,6 @@ export * from './datasource.interface';
3
3
  export * from './event-manager-adapter.interface';
4
4
  export * from './identity.interface';
5
5
  export * from './logged-user-info.interface';
6
- export * from './logger.interface';
7
6
  export * from './module-config.interface';
8
7
  export * from './notification-adapter.interface';
9
8
  export * from './permission.interface';
@@ -88,7 +88,7 @@ export class MultiTenantDataSourceService {
88
88
  throw new BadRequestException({
89
89
  message: `Tenant '${tenantId}' not found`,
90
90
  messageKey: SYSTEM_MESSAGES.TENANT_NOT_FOUND,
91
- messageParams: {
91
+ messageVariables: {
92
92
  tenantId
93
93
  }
94
94
  });
@@ -183,7 +183,7 @@ export class MultiTenantDataSourceService {
183
183
  throw new BadRequestException({
184
184
  message: `Tenant not found. Ensure '${this.tenantHeader}' header is set.`,
185
185
  messageKey: SYSTEM_MESSAGES.TENANT_HEADER_REQUIRED,
186
- messageParams: {
186
+ messageVariables: {
187
187
  header: this.tenantHeader
188
188
  }
189
189
  });