@flusys/nestjs-shared 1.1.0-beta → 1.2.0-rc.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 (198) hide show
  1. package/README.md +146 -1330
  2. package/cjs/classes/api-controller.class.js +325 -49
  3. package/cjs/classes/api-service.class.js +271 -149
  4. package/cjs/classes/handle-custome-db.js +37 -0
  5. package/cjs/classes/index.js +2 -2
  6. package/cjs/classes/winston.logger.class.js +103 -70
  7. package/cjs/constants/index.js +15 -4
  8. package/cjs/constants/message-keys.js +68 -0
  9. package/cjs/constants/permissions.js +287 -0
  10. package/cjs/decorators/api-response.decorator.js +2 -3
  11. package/cjs/decorators/index.js +1 -0
  12. package/cjs/decorators/log-action.decorator.js +149 -0
  13. package/cjs/decorators/require-permission.decorator.js +5 -5
  14. package/cjs/dtos/delete.dto.js +10 -0
  15. package/cjs/dtos/filter-and-pagination.dto.js +24 -34
  16. package/cjs/dtos/get-by-ids.dto.js +65 -0
  17. package/cjs/dtos/identity-response.dto.js +4 -8
  18. package/cjs/dtos/index.js +1 -0
  19. package/cjs/dtos/pagination.dto.js +4 -8
  20. package/cjs/dtos/response-payload.dto.js +68 -112
  21. package/cjs/entities/identity.js +12 -6
  22. package/cjs/entities/index.js +1 -0
  23. package/cjs/entities/raw-type.js +4 -0
  24. package/cjs/entities/user-root.js +15 -15
  25. package/cjs/enums/index.js +20 -0
  26. package/cjs/enums/notification-type.enum.js +17 -0
  27. package/cjs/enums/participant-status.enum.js +17 -0
  28. package/cjs/enums/recurrence-type.enum.js +18 -0
  29. package/cjs/exceptions/base-app.exception.js +151 -0
  30. package/cjs/exceptions/index.js +1 -0
  31. package/cjs/exceptions/permission.exception.js +13 -9
  32. package/cjs/filters/global-exception.filter.js +279 -0
  33. package/cjs/filters/index.js +18 -0
  34. package/cjs/guards/jwt-auth.guard.js +4 -1
  35. package/cjs/guards/permission.guard.js +88 -148
  36. package/cjs/index.js +2 -0
  37. package/cjs/interceptors/idempotency.interceptor.js +1 -1
  38. package/cjs/interceptors/index.js +1 -4
  39. package/cjs/interceptors/set-user-field-on-body.interceptor.js +60 -0
  40. package/cjs/interceptors/slug.interceptor.js +30 -9
  41. package/cjs/interfaces/datasource.interface.js +4 -0
  42. package/cjs/interfaces/event-manager-adapter.interface.js +11 -0
  43. package/cjs/interfaces/index.js +4 -2
  44. package/cjs/interfaces/module-config.interface.js +4 -0
  45. package/cjs/interfaces/notification-adapter.interface.js +11 -0
  46. package/cjs/interfaces/permission.interface.js +1 -1
  47. package/cjs/middlewares/logger.middleware.js +133 -115
  48. package/cjs/modules/cache/cache.module.js +3 -3
  49. package/cjs/modules/datasource/index.js +0 -1
  50. package/cjs/modules/datasource/multi-tenant-datasource.service.js +60 -183
  51. package/cjs/modules/utils/utils.service.js +27 -206
  52. package/cjs/utils/date-time.util.js +94 -0
  53. package/cjs/utils/html-sanitizer.util.js +64 -0
  54. package/cjs/utils/index.js +5 -1
  55. package/cjs/utils/query-helpers.util.js +60 -0
  56. package/cjs/utils/request.util.js +96 -0
  57. package/cjs/utils/string.util.js +63 -0
  58. package/classes/api-controller.class.d.ts +16 -8
  59. package/classes/api-service.class.d.ts +30 -25
  60. package/classes/handle-custome-db.d.ts +3 -0
  61. package/classes/index.d.ts +2 -2
  62. package/classes/winston.logger.class.d.ts +1 -0
  63. package/constants/index.d.ts +2 -1
  64. package/constants/message-keys.d.ts +45 -0
  65. package/constants/permissions.d.ts +306 -0
  66. package/decorators/api-response.decorator.d.ts +1 -1
  67. package/decorators/current-user.decorator.d.ts +1 -1
  68. package/decorators/index.d.ts +1 -0
  69. package/decorators/log-action.decorator.d.ts +8 -0
  70. package/decorators/require-permission.decorator.d.ts +2 -2
  71. package/dtos/delete.dto.d.ts +1 -0
  72. package/dtos/filter-and-pagination.dto.d.ts +0 -2
  73. package/dtos/get-by-ids.dto.d.ts +4 -0
  74. package/dtos/index.d.ts +1 -0
  75. package/dtos/response-payload.dto.d.ts +8 -20
  76. package/entities/index.d.ts +1 -0
  77. package/entities/raw-type.d.ts +1 -0
  78. package/enums/index.d.ts +3 -0
  79. package/enums/notification-type.enum.d.ts +6 -0
  80. package/enums/participant-status.enum.d.ts +6 -0
  81. package/enums/recurrence-type.enum.d.ts +7 -0
  82. package/exceptions/base-app.exception.d.ts +41 -0
  83. package/exceptions/index.d.ts +1 -0
  84. package/exceptions/permission.exception.d.ts +2 -2
  85. package/fesm/classes/api-controller.class.js +326 -50
  86. package/fesm/classes/api-service.class.js +274 -152
  87. package/fesm/classes/handle-custome-db.js +19 -0
  88. package/fesm/classes/index.js +3 -2
  89. package/fesm/classes/winston.logger.class.js +100 -68
  90. package/fesm/constants/index.js +4 -1
  91. package/fesm/constants/message-keys.js +49 -0
  92. package/fesm/constants/permissions.js +200 -0
  93. package/fesm/decorators/api-response.decorator.js +3 -21
  94. package/fesm/decorators/index.js +1 -0
  95. package/fesm/decorators/log-action.decorator.js +139 -0
  96. package/fesm/decorators/require-permission.decorator.js +17 -65
  97. package/fesm/dtos/delete.dto.js +12 -2
  98. package/fesm/dtos/filter-and-pagination.dto.js +26 -47
  99. package/fesm/dtos/get-by-ids.dto.js +55 -0
  100. package/fesm/dtos/identity-response.dto.js +4 -8
  101. package/fesm/dtos/index.js +1 -0
  102. package/fesm/dtos/pagination.dto.js +4 -8
  103. package/fesm/dtos/response-payload.dto.js +68 -103
  104. package/fesm/entities/identity.js +12 -6
  105. package/fesm/entities/index.js +1 -0
  106. package/fesm/entities/raw-type.js +1 -0
  107. package/fesm/entities/user-root.js +15 -15
  108. package/fesm/enums/index.js +3 -0
  109. package/fesm/enums/notification-type.enum.js +7 -0
  110. package/fesm/enums/participant-status.enum.js +7 -0
  111. package/fesm/enums/recurrence-type.enum.js +8 -0
  112. package/fesm/exceptions/base-app.exception.js +115 -0
  113. package/fesm/exceptions/index.js +1 -0
  114. package/fesm/exceptions/permission.exception.js +16 -18
  115. package/fesm/filters/global-exception.filter.js +269 -0
  116. package/fesm/filters/index.js +1 -0
  117. package/fesm/guards/jwt-auth.guard.js +5 -2
  118. package/fesm/guards/permission.guard.js +90 -150
  119. package/fesm/index.js +2 -0
  120. package/fesm/interceptors/idempotency.interceptor.js +2 -2
  121. package/fesm/interceptors/index.js +1 -4
  122. package/fesm/interceptors/set-user-field-on-body.interceptor.js +39 -0
  123. package/fesm/interceptors/slug.interceptor.js +31 -10
  124. package/fesm/interfaces/datasource.interface.js +1 -0
  125. package/fesm/interfaces/event-manager-adapter.interface.js +1 -0
  126. package/fesm/interfaces/index.js +4 -2
  127. package/fesm/interfaces/module-config.interface.js +5 -0
  128. package/fesm/interfaces/notification-adapter.interface.js +1 -0
  129. package/fesm/interfaces/permission.interface.js +1 -3
  130. package/fesm/middlewares/logger.middleware.js +133 -109
  131. package/fesm/modules/cache/cache.module.js +2 -2
  132. package/fesm/modules/datasource/index.js +0 -1
  133. package/fesm/modules/datasource/multi-tenant-datasource.service.js +61 -184
  134. package/fesm/modules/utils/utils.service.js +27 -206
  135. package/fesm/utils/date-time.util.js +70 -0
  136. package/fesm/utils/html-sanitizer.util.js +69 -0
  137. package/fesm/utils/index.js +5 -1
  138. package/fesm/utils/query-helpers.util.js +85 -0
  139. package/fesm/utils/request.util.js +81 -0
  140. package/fesm/utils/string.util.js +71 -0
  141. package/filters/global-exception.filter.d.ts +9 -0
  142. package/filters/index.d.ts +1 -0
  143. package/guards/permission.guard.d.ts +4 -6
  144. package/index.d.ts +2 -0
  145. package/interceptors/idempotency.interceptor.d.ts +1 -1
  146. package/interceptors/index.d.ts +1 -4
  147. package/interceptors/set-user-field-on-body.interceptor.d.ts +5 -0
  148. package/interceptors/slug.interceptor.d.ts +2 -1
  149. package/interfaces/api.interface.d.ts +4 -2
  150. package/interfaces/datasource.interface.d.ts +5 -0
  151. package/interfaces/event-manager-adapter.interface.d.ts +43 -0
  152. package/interfaces/identity.interface.d.ts +4 -4
  153. package/interfaces/index.d.ts +4 -2
  154. package/interfaces/logged-user-info.interface.d.ts +0 -2
  155. package/interfaces/module-config.interface.d.ts +6 -0
  156. package/interfaces/notification-adapter.interface.d.ts +21 -0
  157. package/interfaces/permission.interface.d.ts +13 -9
  158. package/middlewares/logger.middleware.d.ts +2 -2
  159. package/modules/datasource/index.d.ts +0 -1
  160. package/modules/datasource/multi-tenant-datasource.service.d.ts +5 -16
  161. package/modules/utils/utils.service.d.ts +3 -14
  162. package/package.json +21 -14
  163. package/utils/date-time.util.d.ts +8 -0
  164. package/utils/html-sanitizer.util.d.ts +2 -0
  165. package/utils/index.d.ts +5 -1
  166. package/utils/query-helpers.util.d.ts +16 -0
  167. package/utils/request.util.d.ts +6 -0
  168. package/utils/string.util.d.ts +2 -0
  169. package/cjs/classes/request-scoped-api.service.js +0 -61
  170. package/cjs/classes/winston-logger-adapter.class.js +0 -121
  171. package/cjs/interceptors/query-performance.interceptor.js +0 -66
  172. package/cjs/interceptors/set-create-by-on-body.interceptor.js +0 -40
  173. package/cjs/interceptors/set-delete-by-on-body.interceptor.js +0 -40
  174. package/cjs/interceptors/set-update-by-on-body.interceptor.js +0 -40
  175. package/cjs/interfaces/base-query.interface.js +0 -6
  176. package/cjs/interfaces/logger.interface.js +0 -7
  177. package/cjs/modules/datasource/datasource.module.js +0 -120
  178. package/cjs/utils/error-handler.util.js +0 -67
  179. package/classes/request-scoped-api.service.d.ts +0 -13
  180. package/classes/winston-logger-adapter.class.d.ts +0 -20
  181. package/fesm/classes/request-scoped-api.service.js +0 -51
  182. package/fesm/classes/winston-logger-adapter.class.js +0 -124
  183. package/fesm/interceptors/query-performance.interceptor.js +0 -56
  184. package/fesm/interceptors/set-create-by-on-body.interceptor.js +0 -30
  185. package/fesm/interceptors/set-delete-by-on-body.interceptor.js +0 -30
  186. package/fesm/interceptors/set-update-by-on-body.interceptor.js +0 -30
  187. package/fesm/interfaces/base-query.interface.js +0 -3
  188. package/fesm/interfaces/logger.interface.js +0 -4
  189. package/fesm/modules/datasource/datasource.module.js +0 -110
  190. package/fesm/utils/error-handler.util.js +0 -59
  191. package/interceptors/query-performance.interceptor.d.ts +0 -8
  192. package/interceptors/set-create-by-on-body.interceptor.d.ts +0 -5
  193. package/interceptors/set-delete-by-on-body.interceptor.d.ts +0 -5
  194. package/interceptors/set-update-by-on-body.interceptor.d.ts +0 -5
  195. package/interfaces/base-query.interface.d.ts +0 -7
  196. package/interfaces/logger.interface.d.ts +0 -7
  197. package/modules/datasource/datasource.module.d.ts +0 -18
  198. package/utils/error-handler.util.d.ts +0 -24
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  _export_star(require("./delete-empty-id-from-body.interceptor"), exports);
6
6
  _export_star(require("./idempotency.interceptor"), exports);
7
- _export_star(require("./query-performance.interceptor"), exports);
8
7
  _export_star(require("./response-meta.interceptor"), exports);
9
- _export_star(require("./set-create-by-on-body.interceptor"), exports);
10
- _export_star(require("./set-delete-by-on-body.interceptor"), exports);
11
- _export_star(require("./set-update-by-on-body.interceptor"), exports);
8
+ _export_star(require("./set-user-field-on-body.interceptor"), exports);
12
9
  _export_star(require("./slug.interceptor"), exports);
13
10
  function _export_star(from, to) {
14
11
  Object.keys(from).forEach(function(k) {
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get SetCreatedByOnBody () {
13
+ return SetCreatedByOnBody;
14
+ },
15
+ get SetDeletedByOnBody () {
16
+ return SetDeletedByOnBody;
17
+ },
18
+ get SetUpdateByOnBody () {
19
+ return SetUpdateByOnBody;
20
+ },
21
+ get createSetUserFieldInterceptor () {
22
+ return createSetUserFieldInterceptor;
23
+ }
24
+ });
25
+ const _common = require("@nestjs/common");
26
+ function _ts_decorate(decorators, target, key, desc) {
27
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
28
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
29
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
30
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
31
+ }
32
+ function createSetUserFieldInterceptor(fieldName) {
33
+ let SetUserFieldOnBody = class SetUserFieldOnBody {
34
+ intercept(context, next) {
35
+ const request = context.switchToHttp().getRequest();
36
+ const user = request?.user;
37
+ if (user) {
38
+ if (Array.isArray(request.body)) {
39
+ request.body = request.body.map((item)=>({
40
+ ...item,
41
+ [fieldName]: user.id
42
+ }));
43
+ } else if (typeof request.body === 'object' && request.body !== null) {
44
+ request.body = {
45
+ ...request.body,
46
+ [fieldName]: user.id
47
+ };
48
+ }
49
+ }
50
+ return next.handle();
51
+ }
52
+ };
53
+ SetUserFieldOnBody = _ts_decorate([
54
+ (0, _common.Injectable)()
55
+ ], SetUserFieldOnBody);
56
+ return SetUserFieldOnBody;
57
+ }
58
+ const SetCreatedByOnBody = createSetUserFieldInterceptor('createdById');
59
+ const SetUpdateByOnBody = createSetUserFieldInterceptor('updatedById');
60
+ const SetDeletedByOnBody = createSetUserFieldInterceptor('deletedById');
@@ -29,26 +29,47 @@ function _ts_decorate(decorators, target, key, desc) {
29
29
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
30
30
  return c > 3 && r && Object.defineProperty(target, key, r), r;
31
31
  }
32
+ function _ts_metadata(k, v) {
33
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
34
+ }
35
+ function _ts_param(paramIndex, decorator) {
36
+ return function(target, key) {
37
+ decorator(target, key, paramIndex);
38
+ };
39
+ }
32
40
  let Slug = class Slug {
33
41
  intercept(context, next) {
34
42
  const request = context.switchToHttp().getRequest();
35
43
  if (Array.isArray(request.body)) {
36
- request.body = request.body.map((item)=>({
37
- ...item,
38
- slug: item.slug || (item?.name ? this.utilsService.transformToSlug(item.name) : null)
39
- }));
40
- } else if (!request.body.slug) {
44
+ request.body = request.body.map((item)=>{
45
+ // Only generate slug if not provided and name exists
46
+ if (!item.slug && item?.name) {
47
+ return {
48
+ ...item,
49
+ slug: this.utilsService.transformToSlug(item.name)
50
+ };
51
+ }
52
+ return item;
53
+ });
54
+ } else if (!request.body?.slug && request.body?.name) {
55
+ // Only generate slug if not provided and name exists
41
56
  request.body = {
42
57
  ...request.body,
43
- slug: request.body?.name ? this.utilsService.transformToSlug(request.body?.name) : null
58
+ slug: this.utilsService.transformToSlug(request.body.name)
44
59
  };
45
60
  }
46
61
  return next.handle();
47
62
  }
48
- constructor(){
49
- _define_property(this, "utilsService", new _utilsservice.UtilsService());
63
+ constructor(utilsService){
64
+ _define_property(this, "utilsService", void 0);
65
+ this.utilsService = utilsService;
50
66
  }
51
67
  };
52
68
  Slug = _ts_decorate([
53
- (0, _common.Injectable)()
69
+ (0, _common.Injectable)(),
70
+ _ts_param(0, (0, _common.Inject)(_utilsservice.UtilsService)),
71
+ _ts_metadata("design:type", Function),
72
+ _ts_metadata("design:paramtypes", [
73
+ typeof _utilsservice.UtilsService === "undefined" ? Object : _utilsservice.UtilsService
74
+ ])
54
75
  ], Slug);
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "EVENT_MANAGER_ADAPTER", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return EVENT_MANAGER_ADAPTER;
9
+ }
10
+ });
11
+ const EVENT_MANAGER_ADAPTER = 'EVENT_MANAGER_ADAPTER';
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  _export_star(require("./api.interface"), exports);
6
- _export_star(require("./base-query.interface"), exports);
6
+ _export_star(require("./datasource.interface"), exports);
7
+ _export_star(require("./event-manager-adapter.interface"), exports);
7
8
  _export_star(require("./identity.interface"), exports);
8
9
  _export_star(require("./logged-user-info.interface"), exports);
9
- _export_star(require("./logger.interface"), exports);
10
+ _export_star(require("./module-config.interface"), exports);
11
+ _export_star(require("./notification-adapter.interface"), exports);
10
12
  _export_star(require("./permission.interface"), exports);
11
13
  function _export_star(from, to) {
12
14
  Object.keys(from).forEach(function(k) {
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "NOTIFICATION_ADAPTER", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return NOTIFICATION_ADAPTER;
9
+ }
10
+ });
11
+ const NOTIFICATION_ADAPTER = 'NOTIFICATION_ADAPTER';
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ /** Action node - checks a single permission/action code */ "use strict";
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
@@ -26,12 +26,6 @@ _export(exports, {
26
26
  },
27
27
  get requestContext () {
28
28
  return requestContext;
29
- },
30
- get setCompanyId () {
31
- return setCompanyId;
32
- },
33
- get setUserId () {
34
- return setUserId;
35
29
  }
36
30
  });
37
31
  const _config = require("@flusys/nestjs-core/config");
@@ -60,44 +54,87 @@ function _ts_decorate(decorators, target, key, desc) {
60
54
  return c > 3 && r && Object.defineProperty(target, key, r), r;
61
55
  }
62
56
  // Configuration
63
- const IS_DEBUG = _config.envConfig.getLogConfig().level === 'debug';
57
+ const logConfig = _config.envConfig.getLogConfig();
58
+ const IS_DEBUG = logConfig.level === 'debug';
59
+ const DISABLE_HTTP_LOGGING = logConfig.disableHttpLogging;
64
60
  const TENANT_ID_HEADER = 'x-tenant-id';
65
61
  const EXCLUDED_PATHS = [
66
62
  '/health',
67
63
  '/metrics',
68
64
  '/favicon.ico'
69
65
  ];
70
- const EXCLUDED_HEADERS = [
71
- 'authorization',
72
- 'cookie',
73
- 'x-api-key'
74
- ];
75
66
  const MAX_BODY_LOG_SIZE = 1000;
76
67
  const requestContext = new _async_hooks.AsyncLocalStorage();
77
68
  const getRequestId = ()=>requestContext.getStore()?.requestId;
78
69
  const getTenantId = ()=>requestContext.getStore()?.tenantId;
79
70
  const getUserId = ()=>requestContext.getStore()?.userId;
80
71
  const getCompanyId = ()=>requestContext.getStore()?.companyId;
81
- const setUserId = (userId)=>{
82
- const store = requestContext.getStore();
83
- if (store) store.userId = userId;
84
- };
85
- const setCompanyId = (companyId)=>{
86
- const store = requestContext.getStore();
87
- if (store) store.companyId = companyId;
88
- };
89
72
  // Helper Functions
90
- function sanitizeHeaders(headers) {
91
- const sanitized = {};
92
- for (const [key, value] of Object.entries(headers)){
93
- sanitized[key] = EXCLUDED_HEADERS.includes(key.toLowerCase()) ? '[REDACTED]' : value;
73
+ function summarizeRequestBody(body) {
74
+ if (!body) return undefined;
75
+ const parsed = typeof body === 'string' ? tryParseJson(body) : body;
76
+ if (!parsed || typeof parsed !== 'object') {
77
+ const str = String(body);
78
+ return str.length > MAX_BODY_LOG_SIZE ? str.substring(0, MAX_BODY_LOG_SIZE) + '...' : str;
94
79
  }
95
- return sanitized;
80
+ // For API request bodies, provide a concise summary
81
+ const summary = {};
82
+ // Pagination info
83
+ if (parsed.pagination) {
84
+ summary.page = parsed.pagination.currentPage;
85
+ summary.pageSize = parsed.pagination.pageSize;
86
+ }
87
+ // Filter keys only (not values - may contain sensitive data)
88
+ if (parsed.filter && typeof parsed.filter === 'object') {
89
+ const filterKeys = Object.keys(parsed.filter);
90
+ if (filterKeys.length > 0) summary.filterKeys = filterKeys;
91
+ }
92
+ // Select fields count
93
+ if (Array.isArray(parsed.select) && parsed.select.length > 0) {
94
+ summary.selectCount = parsed.select.length;
95
+ }
96
+ // Sort keys
97
+ if (parsed.sort && typeof parsed.sort === 'object') {
98
+ const sortKeys = Object.keys(parsed.sort);
99
+ if (sortKeys.length > 0) summary.sortKeys = sortKeys;
100
+ }
101
+ // ID for single item operations
102
+ if (parsed.id) summary.id = parsed.id;
103
+ // IDs for bulk operations
104
+ if (Array.isArray(parsed.ids)) summary.idsCount = parsed.ids.length;
105
+ return Object.keys(summary).length > 0 ? JSON.stringify(summary) : '{}';
96
106
  }
97
- function truncateBody(body) {
107
+ function summarizeResponseBody(body) {
98
108
  if (!body) return undefined;
99
- const str = typeof body === 'string' ? body : JSON.stringify(body);
100
- return str.length > MAX_BODY_LOG_SIZE ? str.substring(0, MAX_BODY_LOG_SIZE) + '...' : body;
109
+ const parsed = typeof body === 'string' ? tryParseJson(body) : body;
110
+ if (!parsed || typeof parsed !== 'object') {
111
+ const str = String(body);
112
+ return str.length > MAX_BODY_LOG_SIZE ? str.substring(0, MAX_BODY_LOG_SIZE) + '...' : str;
113
+ }
114
+ const summary = {};
115
+ if ('success' in parsed) summary.success = parsed.success;
116
+ if ('message' in parsed) summary.message = parsed.message;
117
+ if ('code' in parsed) summary.code = parsed.code;
118
+ if (Array.isArray(parsed.data)) {
119
+ summary.dataCount = parsed.data.length;
120
+ } else if (parsed.data && typeof parsed.data === 'object') {
121
+ summary.hasData = true;
122
+ }
123
+ if (parsed.meta) {
124
+ summary.total = parsed.meta.total;
125
+ summary.page = parsed.meta.page;
126
+ }
127
+ if (parsed.errors) {
128
+ summary.errorsCount = Array.isArray(parsed.errors) ? parsed.errors.length : 1;
129
+ }
130
+ return JSON.stringify(summary);
131
+ }
132
+ function tryParseJson(str) {
133
+ try {
134
+ return JSON.parse(str);
135
+ } catch {
136
+ return null;
137
+ }
101
138
  }
102
139
  function getClientIp(req) {
103
140
  return req.headers['x-forwarded-for']?.split(',')[0] || req.socket?.remoteAddress || 'unknown';
@@ -107,136 +144,117 @@ let LoggerMiddleware = class LoggerMiddleware {
107
144
  const requestId = req.headers[_constants.REQUEST_ID_HEADER] || (0, _uuid.v4)();
108
145
  const tenantId = req.headers[TENANT_ID_HEADER];
109
146
  const startTime = Date.now();
110
- // Set response header
111
147
  res.setHeader(_constants.REQUEST_ID_HEADER, requestId);
112
- // Create context
113
148
  const context = {
114
149
  requestId,
115
150
  tenantId,
116
151
  startTime
117
152
  };
118
- // Run in AsyncLocalStorage context
119
153
  requestContext.run(context, ()=>{
120
- // Check if we should skip logging
121
- const shouldSkipLogging = EXCLUDED_PATHS.some((path)=>req.originalUrl.startsWith(path));
154
+ const shouldSkipLogging = DISABLE_HTTP_LOGGING || EXCLUDED_PATHS.some((path)=>req.originalUrl.startsWith(path));
122
155
  if (!shouldSkipLogging) {
123
156
  this.logRequest(req, requestId, tenantId);
124
- // Track if response was already logged
125
- let responseLogged = false;
126
- // Capture response using multiple hooks to ensure we catch it
127
- const originalSend = res.send;
128
- const originalJson = res.json;
129
- const originalEnd = res.end;
130
- // Store reference to this for use in callbacks
131
- const self = this;
132
- // Override res.send
133
- res.send = function(body) {
134
- if (!responseLogged) {
135
- responseLogged = true;
136
- self.logResponse(req, res, startTime, body, requestId, tenantId);
137
- }
138
- return originalSend.call(this, body);
139
- };
140
- // Override res.json
141
- res.json = function(body) {
142
- if (!responseLogged) {
143
- responseLogged = true;
144
- self.logResponse(req, res, startTime, body, requestId, tenantId);
145
- }
146
- return originalJson.call(this, body);
147
- };
148
- // Override res.end as fallback
149
- res.end = function(...args) {
150
- if (!responseLogged) {
151
- responseLogged = true;
152
- self.logResponse(req, res, startTime, args[0], requestId, tenantId);
153
- }
154
- return originalEnd.apply(this, args);
155
- };
156
- // Handle errors
157
- res.on('error', (error)=>{
158
- this.logger.error('Response error', {
159
- context: 'HTTP',
160
- requestId,
161
- tenantId,
162
- method: req.method,
163
- url: req.originalUrl,
164
- path: req.path,
165
- error: error.message,
166
- stack: error.stack
167
- });
168
- });
157
+ this.setupResponseLogging(req, res, startTime, requestId, tenantId);
169
158
  }
170
159
  next();
171
160
  });
172
161
  }
162
+ setupResponseLogging(req, res, startTime, requestId, tenantId) {
163
+ let responseLogged = false;
164
+ const originalSend = res.send;
165
+ const originalJson = res.json;
166
+ const originalEnd = res.end;
167
+ const self = this;
168
+ const logOnce = (body)=>{
169
+ if (!responseLogged) {
170
+ responseLogged = true;
171
+ self.logResponse(req, res, startTime, body, requestId, tenantId);
172
+ }
173
+ };
174
+ res.send = function(body) {
175
+ logOnce(body);
176
+ return originalSend.call(this, body);
177
+ };
178
+ res.json = function(body) {
179
+ logOnce(body);
180
+ return originalJson.call(this, body);
181
+ };
182
+ res.end = function(...args) {
183
+ logOnce(args[0]);
184
+ return originalEnd.apply(this, args);
185
+ };
186
+ res.on('error', (error)=>{
187
+ this.logger.error('Response error', {
188
+ ...this.buildBaseLogData(req, requestId, tenantId),
189
+ error: error.message,
190
+ stack: error.stack
191
+ });
192
+ });
193
+ }
173
194
  logRequest(req, requestId, tenantId) {
195
+ const ip = getClientIp(req);
196
+ const contentType = req.headers['content-type'] || 'none';
197
+ // Build descriptive message like: Started processing request "POST" "/api/users" from "192.168.1.1"
198
+ const message = `Started processing request "${req.method}" "${req.originalUrl}" from "${ip}"`;
174
199
  const logData = {
175
- context: 'HTTP',
176
- requestId,
177
- tenantId,
178
- method: req.method,
179
- url: req.originalUrl,
180
- path: req.path,
200
+ ...this.buildBaseLogData(req, requestId, tenantId),
181
201
  query: Object.keys(req.query).length > 0 ? req.query : undefined,
182
- ip: getClientIp(req),
202
+ ip,
183
203
  userAgent: req.headers['user-agent'],
184
- contentType: req.headers['content-type'],
204
+ contentType,
185
205
  contentLength: req.headers['content-length']
186
206
  };
187
- // Add debug details if enabled
188
207
  if (IS_DEBUG) {
189
- logData.headers = sanitizeHeaders(req.headers);
190
- logData.body = truncateBody(req.body);
191
- logData.params = Object.keys(req.params).length > 0 ? req.params : undefined;
208
+ logData.body = summarizeRequestBody(req.body);
192
209
  }
193
- this.logger.info('Incoming request', logData);
210
+ this.logger.info(message, logData);
194
211
  }
195
212
  logResponse(req, res, startTime, body, requestId, tenantId) {
196
213
  const duration = Date.now() - startTime;
197
214
  const statusCode = res.statusCode;
198
215
  const level = statusCode >= 500 ? 'error' : statusCode >= 400 ? 'warn' : 'info';
216
+ const userId = getUserId();
217
+ const companyId = getCompanyId();
218
+ const contentType = res.getHeader('content-type') || 'none';
219
+ const contentLength = res.getHeader('content-length') || 'null';
220
+ // Build descriptive message like: Request finished "HTTP/1.1" "POST" "/api/users" - 200 "application/json" 534.29ms
221
+ const message = `Request finished "HTTP/1.1" "${req.method}" "${req.originalUrl}" - ${statusCode} ${contentLength} "${contentType}" ${duration.toFixed(2)}ms`;
199
222
  const logData = {
200
- context: 'HTTP',
201
- requestId,
202
- tenantId,
203
- method: req.method,
204
- url: req.originalUrl,
205
- path: req.path,
223
+ ...this.buildBaseLogData(req, requestId, tenantId),
224
+ userId,
225
+ companyId,
206
226
  statusCode,
207
227
  statusMessage: res.statusMessage,
208
228
  duration: `${duration}ms`,
209
229
  durationMs: duration,
210
- contentType: res.getHeader('content-type'),
211
- contentLength: res.getHeader('content-length')
230
+ contentType,
231
+ contentLength
212
232
  };
213
- // Add user context if available
214
- const userId = getUserId();
215
- const companyId = getCompanyId();
216
- if (userId) logData.userId = userId;
217
- if (companyId) logData.companyId = companyId;
218
- // Add response body for errors or debug mode
219
233
  if (statusCode >= 400 || IS_DEBUG) {
220
- logData.responseBody = truncateBody(body);
234
+ logData.responseBody = summarizeResponseBody(body);
221
235
  }
222
- this.logger.log(level, `Response [${statusCode}]`, logData);
223
- // Log slow requests separately
236
+ this.logger.log(level, message, logData);
224
237
  if (duration > 3000 && statusCode < 400) {
225
- this.logger.warn('Slow request detected', {
226
- context: 'HTTP',
227
- requestId,
228
- tenantId,
238
+ this.logger.warn(`Slow request detected: "${req.method}" "${req.originalUrl}" took ${duration}ms (threshold: 3000ms)`, {
239
+ ...this.buildBaseLogData(req, requestId, tenantId),
229
240
  userId,
230
241
  companyId,
231
- method: req.method,
232
- url: req.originalUrl,
233
- path: req.path,
234
242
  duration: `${duration}ms`,
235
243
  durationMs: duration,
236
244
  threshold: '3000ms'
237
245
  });
238
246
  }
239
247
  }
248
+ buildBaseLogData(req, requestId, tenantId) {
249
+ return {
250
+ context: 'HTTP',
251
+ requestId,
252
+ tenantId,
253
+ method: req.method,
254
+ url: req.originalUrl,
255
+ path: req.path
256
+ };
257
+ }
240
258
  constructor(){
241
259
  _define_property(this, "logger", _winstonloggerclass.instance);
242
260
  }
@@ -8,8 +8,8 @@ Object.defineProperty(exports, "CacheModule", {
8
8
  return CacheModule;
9
9
  }
10
10
  });
11
- const _classes = require("@flusys/nestjs-shared/classes");
12
- const _constants = require("@flusys/nestjs-shared/constants");
11
+ const _hybridcacheclass = require("../../classes/hybrid-cache.class");
12
+ const _constants = require("../../constants");
13
13
  const _common = require("@nestjs/common");
14
14
  function _ts_decorate(decorators, target, key, desc) {
15
15
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -25,7 +25,7 @@ let CacheModule = class CacheModule {
25
25
  providers: [
26
26
  {
27
27
  provide: _constants.CACHE_INSTANCE,
28
- useFactory: ()=>new _classes.HybridCache(memoryTtl, memorySize)
28
+ useFactory: ()=>new _hybridcacheclass.HybridCache(memoryTtl, memorySize)
29
29
  }
30
30
  ],
31
31
  exports: [
@@ -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) {