@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
@@ -24,18 +24,15 @@ import { v4 as uuidv4 } from 'uuid';
24
24
  import { instance as winstonLogger } from '../classes/winston.logger.class';
25
25
  import { REQUEST_ID_HEADER } from '../constants';
26
26
  // Configuration
27
- const IS_DEBUG = envConfig.getLogConfig().level === 'debug';
27
+ const logConfig = envConfig.getLogConfig();
28
+ const IS_DEBUG = logConfig.level === 'debug';
29
+ const DISABLE_HTTP_LOGGING = logConfig.disableHttpLogging;
28
30
  const TENANT_ID_HEADER = 'x-tenant-id';
29
31
  const EXCLUDED_PATHS = [
30
32
  '/health',
31
33
  '/metrics',
32
34
  '/favicon.ico'
33
35
  ];
34
- const EXCLUDED_HEADERS = [
35
- 'authorization',
36
- 'cookie',
37
- 'x-api-key'
38
- ];
39
36
  const MAX_BODY_LOG_SIZE = 1000;
40
37
  export const requestContext = new AsyncLocalStorage();
41
38
  // Context accessors
@@ -43,26 +40,72 @@ export const getRequestId = ()=>requestContext.getStore()?.requestId;
43
40
  export const getTenantId = ()=>requestContext.getStore()?.tenantId;
44
41
  export const getUserId = ()=>requestContext.getStore()?.userId;
45
42
  export const getCompanyId = ()=>requestContext.getStore()?.companyId;
46
- export const setUserId = (userId)=>{
47
- const store = requestContext.getStore();
48
- if (store) store.userId = userId;
49
- };
50
- export const setCompanyId = (companyId)=>{
51
- const store = requestContext.getStore();
52
- if (store) store.companyId = companyId;
53
- };
54
43
  // Helper Functions
55
- function sanitizeHeaders(headers) {
56
- const sanitized = {};
57
- for (const [key, value] of Object.entries(headers)){
58
- sanitized[key] = EXCLUDED_HEADERS.includes(key.toLowerCase()) ? '[REDACTED]' : value;
44
+ function summarizeRequestBody(body) {
45
+ if (!body) return undefined;
46
+ const parsed = typeof body === 'string' ? tryParseJson(body) : body;
47
+ if (!parsed || typeof parsed !== 'object') {
48
+ const str = String(body);
49
+ return str.length > MAX_BODY_LOG_SIZE ? str.substring(0, MAX_BODY_LOG_SIZE) + '...' : str;
50
+ }
51
+ // For API request bodies, provide a concise summary
52
+ const summary = {};
53
+ // Pagination info
54
+ if (parsed.pagination) {
55
+ summary.page = parsed.pagination.currentPage;
56
+ summary.pageSize = parsed.pagination.pageSize;
57
+ }
58
+ // Filter keys only (not values - may contain sensitive data)
59
+ if (parsed.filter && typeof parsed.filter === 'object') {
60
+ const filterKeys = Object.keys(parsed.filter);
61
+ if (filterKeys.length > 0) summary.filterKeys = filterKeys;
62
+ }
63
+ // Select fields count
64
+ if (Array.isArray(parsed.select) && parsed.select.length > 0) {
65
+ summary.selectCount = parsed.select.length;
66
+ }
67
+ // Sort keys
68
+ if (parsed.sort && typeof parsed.sort === 'object') {
69
+ const sortKeys = Object.keys(parsed.sort);
70
+ if (sortKeys.length > 0) summary.sortKeys = sortKeys;
59
71
  }
60
- return sanitized;
72
+ // ID for single item operations
73
+ if (parsed.id) summary.id = parsed.id;
74
+ // IDs for bulk operations
75
+ if (Array.isArray(parsed.ids)) summary.idsCount = parsed.ids.length;
76
+ return Object.keys(summary).length > 0 ? JSON.stringify(summary) : '{}';
61
77
  }
62
- function truncateBody(body) {
78
+ function summarizeResponseBody(body) {
63
79
  if (!body) return undefined;
64
- const str = typeof body === 'string' ? body : JSON.stringify(body);
65
- return str.length > MAX_BODY_LOG_SIZE ? str.substring(0, MAX_BODY_LOG_SIZE) + '...' : body;
80
+ const parsed = typeof body === 'string' ? tryParseJson(body) : body;
81
+ if (!parsed || typeof parsed !== 'object') {
82
+ const str = String(body);
83
+ return str.length > MAX_BODY_LOG_SIZE ? str.substring(0, MAX_BODY_LOG_SIZE) + '...' : str;
84
+ }
85
+ const summary = {};
86
+ if ('success' in parsed) summary.success = parsed.success;
87
+ if ('message' in parsed) summary.message = parsed.message;
88
+ if ('code' in parsed) summary.code = parsed.code;
89
+ if (Array.isArray(parsed.data)) {
90
+ summary.dataCount = parsed.data.length;
91
+ } else if (parsed.data && typeof parsed.data === 'object') {
92
+ summary.hasData = true;
93
+ }
94
+ if (parsed.meta) {
95
+ summary.total = parsed.meta.total;
96
+ summary.page = parsed.meta.page;
97
+ }
98
+ if (parsed.errors) {
99
+ summary.errorsCount = Array.isArray(parsed.errors) ? parsed.errors.length : 1;
100
+ }
101
+ return JSON.stringify(summary);
102
+ }
103
+ function tryParseJson(str) {
104
+ try {
105
+ return JSON.parse(str);
106
+ } catch {
107
+ return null;
108
+ }
66
109
  }
67
110
  function getClientIp(req) {
68
111
  return req.headers['x-forwarded-for']?.split(',')[0] || req.socket?.remoteAddress || 'unknown';
@@ -72,136 +115,117 @@ export class LoggerMiddleware {
72
115
  const requestId = req.headers[REQUEST_ID_HEADER] || uuidv4();
73
116
  const tenantId = req.headers[TENANT_ID_HEADER];
74
117
  const startTime = Date.now();
75
- // Set response header
76
118
  res.setHeader(REQUEST_ID_HEADER, requestId);
77
- // Create context
78
119
  const context = {
79
120
  requestId,
80
121
  tenantId,
81
122
  startTime
82
123
  };
83
- // Run in AsyncLocalStorage context
84
124
  requestContext.run(context, ()=>{
85
- // Check if we should skip logging
86
- const shouldSkipLogging = EXCLUDED_PATHS.some((path)=>req.originalUrl.startsWith(path));
125
+ const shouldSkipLogging = DISABLE_HTTP_LOGGING || EXCLUDED_PATHS.some((path)=>req.originalUrl.startsWith(path));
87
126
  if (!shouldSkipLogging) {
88
127
  this.logRequest(req, requestId, tenantId);
89
- // Track if response was already logged
90
- let responseLogged = false;
91
- // Capture response using multiple hooks to ensure we catch it
92
- const originalSend = res.send;
93
- const originalJson = res.json;
94
- const originalEnd = res.end;
95
- // Store reference to this for use in callbacks
96
- const self = this;
97
- // Override res.send
98
- res.send = function(body) {
99
- if (!responseLogged) {
100
- responseLogged = true;
101
- self.logResponse(req, res, startTime, body, requestId, tenantId);
102
- }
103
- return originalSend.call(this, body);
104
- };
105
- // Override res.json
106
- res.json = function(body) {
107
- if (!responseLogged) {
108
- responseLogged = true;
109
- self.logResponse(req, res, startTime, body, requestId, tenantId);
110
- }
111
- return originalJson.call(this, body);
112
- };
113
- // Override res.end as fallback
114
- res.end = function(...args) {
115
- if (!responseLogged) {
116
- responseLogged = true;
117
- self.logResponse(req, res, startTime, args[0], requestId, tenantId);
118
- }
119
- return originalEnd.apply(this, args);
120
- };
121
- // Handle errors
122
- res.on('error', (error)=>{
123
- this.logger.error('Response error', {
124
- context: 'HTTP',
125
- requestId,
126
- tenantId,
127
- method: req.method,
128
- url: req.originalUrl,
129
- path: req.path,
130
- error: error.message,
131
- stack: error.stack
132
- });
133
- });
128
+ this.setupResponseLogging(req, res, startTime, requestId, tenantId);
134
129
  }
135
130
  next();
136
131
  });
137
132
  }
133
+ setupResponseLogging(req, res, startTime, requestId, tenantId) {
134
+ let responseLogged = false;
135
+ const originalSend = res.send;
136
+ const originalJson = res.json;
137
+ const originalEnd = res.end;
138
+ const self = this;
139
+ const logOnce = (body)=>{
140
+ if (!responseLogged) {
141
+ responseLogged = true;
142
+ self.logResponse(req, res, startTime, body, requestId, tenantId);
143
+ }
144
+ };
145
+ res.send = function(body) {
146
+ logOnce(body);
147
+ return originalSend.call(this, body);
148
+ };
149
+ res.json = function(body) {
150
+ logOnce(body);
151
+ return originalJson.call(this, body);
152
+ };
153
+ res.end = function(...args) {
154
+ logOnce(args[0]);
155
+ return originalEnd.apply(this, args);
156
+ };
157
+ res.on('error', (error)=>{
158
+ this.logger.error('Response error', {
159
+ ...this.buildBaseLogData(req, requestId, tenantId),
160
+ error: error.message,
161
+ stack: error.stack
162
+ });
163
+ });
164
+ }
138
165
  logRequest(req, requestId, tenantId) {
166
+ const ip = getClientIp(req);
167
+ const contentType = req.headers['content-type'] || 'none';
168
+ // Build descriptive message like: Started processing request "POST" "/api/users" from "192.168.1.1"
169
+ const message = `Started processing request "${req.method}" "${req.originalUrl}" from "${ip}"`;
139
170
  const logData = {
140
- context: 'HTTP',
141
- requestId,
142
- tenantId,
143
- method: req.method,
144
- url: req.originalUrl,
145
- path: req.path,
171
+ ...this.buildBaseLogData(req, requestId, tenantId),
146
172
  query: Object.keys(req.query).length > 0 ? req.query : undefined,
147
- ip: getClientIp(req),
173
+ ip,
148
174
  userAgent: req.headers['user-agent'],
149
- contentType: req.headers['content-type'],
175
+ contentType,
150
176
  contentLength: req.headers['content-length']
151
177
  };
152
- // Add debug details if enabled
153
178
  if (IS_DEBUG) {
154
- logData.headers = sanitizeHeaders(req.headers);
155
- logData.body = truncateBody(req.body);
156
- logData.params = Object.keys(req.params).length > 0 ? req.params : undefined;
179
+ logData.body = summarizeRequestBody(req.body);
157
180
  }
158
- this.logger.info('Incoming request', logData);
181
+ this.logger.info(message, logData);
159
182
  }
160
183
  logResponse(req, res, startTime, body, requestId, tenantId) {
161
184
  const duration = Date.now() - startTime;
162
185
  const statusCode = res.statusCode;
163
186
  const level = statusCode >= 500 ? 'error' : statusCode >= 400 ? 'warn' : 'info';
187
+ const userId = getUserId();
188
+ const companyId = getCompanyId();
189
+ const contentType = res.getHeader('content-type') || 'none';
190
+ const contentLength = res.getHeader('content-length') || 'null';
191
+ // Build descriptive message like: Request finished "HTTP/1.1" "POST" "/api/users" - 200 "application/json" 534.29ms
192
+ const message = `Request finished "HTTP/1.1" "${req.method}" "${req.originalUrl}" - ${statusCode} ${contentLength} "${contentType}" ${duration.toFixed(2)}ms`;
164
193
  const logData = {
165
- context: 'HTTP',
166
- requestId,
167
- tenantId,
168
- method: req.method,
169
- url: req.originalUrl,
170
- path: req.path,
194
+ ...this.buildBaseLogData(req, requestId, tenantId),
195
+ userId,
196
+ companyId,
171
197
  statusCode,
172
198
  statusMessage: res.statusMessage,
173
199
  duration: `${duration}ms`,
174
200
  durationMs: duration,
175
- contentType: res.getHeader('content-type'),
176
- contentLength: res.getHeader('content-length')
201
+ contentType,
202
+ contentLength
177
203
  };
178
- // Add user context if available
179
- const userId = getUserId();
180
- const companyId = getCompanyId();
181
- if (userId) logData.userId = userId;
182
- if (companyId) logData.companyId = companyId;
183
- // Add response body for errors or debug mode
184
204
  if (statusCode >= 400 || IS_DEBUG) {
185
- logData.responseBody = truncateBody(body);
205
+ logData.responseBody = summarizeResponseBody(body);
186
206
  }
187
- this.logger.log(level, `Response [${statusCode}]`, logData);
188
- // Log slow requests separately
207
+ this.logger.log(level, message, logData);
189
208
  if (duration > 3000 && statusCode < 400) {
190
- this.logger.warn('Slow request detected', {
191
- context: 'HTTP',
192
- requestId,
193
- tenantId,
209
+ this.logger.warn(`Slow request detected: "${req.method}" "${req.originalUrl}" took ${duration}ms (threshold: 3000ms)`, {
210
+ ...this.buildBaseLogData(req, requestId, tenantId),
194
211
  userId,
195
212
  companyId,
196
- method: req.method,
197
- url: req.originalUrl,
198
- path: req.path,
199
213
  duration: `${duration}ms`,
200
214
  durationMs: duration,
201
215
  threshold: '3000ms'
202
216
  });
203
217
  }
204
218
  }
219
+ buildBaseLogData(req, requestId, tenantId) {
220
+ return {
221
+ context: 'HTTP',
222
+ requestId,
223
+ tenantId,
224
+ method: req.method,
225
+ url: req.originalUrl,
226
+ path: req.path
227
+ };
228
+ }
205
229
  constructor(){
206
230
  _define_property(this, "logger", winstonLogger);
207
231
  }
@@ -4,8 +4,8 @@ function _ts_decorate(decorators, target, key, desc) {
4
4
  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;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  }
7
- import { HybridCache } from '@flusys/nestjs-shared/classes';
8
- import { CACHE_INSTANCE } from '@flusys/nestjs-shared/constants';
7
+ import { HybridCache } from '../../classes/hybrid-cache.class';
8
+ import { CACHE_INSTANCE } from '../../constants';
9
9
  import { Module } from '@nestjs/common';
10
10
  export class CacheModule {
11
11
  static forRoot(isGlobal = true, memoryTtl = 60_000, memorySize = 5000) {
@@ -1,2 +1 @@
1
- export * from './datasource.module';
2
1
  export * from './multi-tenant-datasource.service';