@nest-omni/core 3.1.2-7 → 3.1.2-8

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 (63) hide show
  1. package/common/utils.d.ts +1 -0
  2. package/common/utils.js +6 -0
  3. package/http-client/config/http-client.config.d.ts +6 -0
  4. package/http-client/config/http-client.config.js +87 -0
  5. package/http-client/config/index.d.ts +1 -0
  6. package/http-client/config/index.js +17 -0
  7. package/http-client/decorators/http-client.decorators.d.ts +72 -0
  8. package/http-client/decorators/http-client.decorators.js +204 -0
  9. package/http-client/decorators/index.d.ts +1 -0
  10. package/http-client/decorators/index.js +17 -0
  11. package/http-client/entities/http-log.entity.d.ts +98 -0
  12. package/http-client/entities/http-log.entity.js +143 -0
  13. package/http-client/entities/index.d.ts +1 -0
  14. package/http-client/entities/index.js +17 -0
  15. package/http-client/errors/http-client.errors.d.ts +56 -0
  16. package/http-client/errors/http-client.errors.js +149 -0
  17. package/http-client/errors/index.d.ts +1 -0
  18. package/http-client/errors/index.js +17 -0
  19. package/http-client/examples/advanced-usage.example.d.ts +23 -0
  20. package/http-client/examples/advanced-usage.example.js +319 -0
  21. package/http-client/examples/basic-usage.example.d.ts +61 -0
  22. package/http-client/examples/basic-usage.example.js +171 -0
  23. package/http-client/examples/index.d.ts +3 -0
  24. package/http-client/examples/index.js +19 -0
  25. package/http-client/examples/multi-api-configuration.example.d.ts +98 -0
  26. package/http-client/examples/multi-api-configuration.example.js +353 -0
  27. package/http-client/http-client.module.d.ts +11 -0
  28. package/http-client/http-client.module.js +254 -0
  29. package/http-client/index.d.ts +10 -0
  30. package/http-client/index.js +27 -0
  31. package/http-client/interfaces/api-client-config.interface.d.ts +152 -0
  32. package/http-client/interfaces/api-client-config.interface.js +12 -0
  33. package/http-client/interfaces/http-client-config.interface.d.ts +123 -0
  34. package/http-client/interfaces/http-client-config.interface.js +2 -0
  35. package/http-client/services/api-client-registry.service.d.ts +40 -0
  36. package/http-client/services/api-client-registry.service.js +411 -0
  37. package/http-client/services/cache.service.d.ts +24 -0
  38. package/http-client/services/cache.service.js +264 -0
  39. package/http-client/services/circuit-breaker.service.d.ts +33 -0
  40. package/http-client/services/circuit-breaker.service.js +180 -0
  41. package/http-client/services/http-client.service.d.ts +43 -0
  42. package/http-client/services/http-client.service.js +384 -0
  43. package/http-client/services/http-log-query.service.d.ts +56 -0
  44. package/http-client/services/http-log-query.service.js +414 -0
  45. package/http-client/services/index.d.ts +7 -0
  46. package/http-client/services/index.js +23 -0
  47. package/http-client/services/log-cleanup.service.d.ts +64 -0
  48. package/http-client/services/log-cleanup.service.js +268 -0
  49. package/http-client/services/logging.service.d.ts +36 -0
  50. package/http-client/services/logging.service.js +445 -0
  51. package/http-client/utils/call-stack-extractor.util.d.ts +29 -0
  52. package/http-client/utils/call-stack-extractor.util.js +138 -0
  53. package/http-client/utils/context-extractor.util.d.ts +44 -0
  54. package/http-client/utils/context-extractor.util.js +173 -0
  55. package/http-client/utils/curl-generator.util.d.ts +9 -0
  56. package/http-client/utils/curl-generator.util.js +169 -0
  57. package/http-client/utils/index.d.ts +4 -0
  58. package/http-client/utils/index.js +20 -0
  59. package/http-client/utils/retry-recorder.util.d.ts +30 -0
  60. package/http-client/utils/retry-recorder.util.js +143 -0
  61. package/index.d.ts +1 -0
  62. package/index.js +1 -0
  63. package/package.json +1 -1
@@ -0,0 +1,445 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ var HttpLoggingService_1;
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.HttpLoggingService = void 0;
23
+ const common_1 = require("@nestjs/common");
24
+ const typeorm_1 = require("typeorm");
25
+ const http_log_entity_1 = require("../entities/http-log.entity");
26
+ const request_id_util_1 = require("../../../../http-client/src/utils/request-id.util");
27
+ const context_extractor_util_1 = require("../utils/context-extractor.util");
28
+ const call_stack_extractor_util_1 = require("../utils/call-stack-extractor.util");
29
+ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
30
+ constructor(dataSource) {
31
+ this.dataSource = dataSource;
32
+ this.logger = new common_1.Logger(HttpLoggingService_1.name);
33
+ this.logRepository = null;
34
+ if (dataSource) {
35
+ this.initializeDatabaseLogging();
36
+ }
37
+ }
38
+ logRequestStart(config, loggingOptions, requestId) {
39
+ const context = context_extractor_util_1.ContextExtractor.getHttpContext();
40
+ const actualRequestId = requestId || context.requestId || (0, request_id_util_1.generateRequestId)();
41
+ const { logHeaders = true, logBody = true, sanitizeHeaders = [], } = loggingOptions || {};
42
+ const logData = {
43
+ requestId: actualRequestId,
44
+ userId: context.userId,
45
+ method: config.method ? config.method.toUpperCase() : 'GET',
46
+ url: config.url,
47
+ headers: logHeaders
48
+ ? this.sanitizeHeaders(config.headers, sanitizeHeaders)
49
+ : undefined,
50
+ body: logBody ? this.sanitizeBody(config.data) : undefined,
51
+ clientIp: context.clientIp,
52
+ serviceName: context.appId,
53
+ };
54
+ const logMessage = `HTTP Request [${actualRequestId}]: ${logData.method} ${logData.url}`;
55
+ switch ((loggingOptions || {}).logLevel) {
56
+ case 'debug':
57
+ this.logger.debug(logMessage, logData);
58
+ break;
59
+ case 'info':
60
+ default:
61
+ this.logger.log(logMessage, logData);
62
+ break;
63
+ }
64
+ return actualRequestId;
65
+ }
66
+ logRequestSuccess(response, startTime, requestId, loggingOptions, databaseLogging = false, retryRecords, cacheHit, circuitBreakerState, decoratorContext) {
67
+ var _a, _b;
68
+ const { logHeaders = true, logBody = true, sanitizeHeaders = [], } = loggingOptions || {};
69
+ const responseTime = Date.now() - startTime;
70
+ const context = context_extractor_util_1.ContextExtractor.getHttpContext();
71
+ const logData = {
72
+ requestId,
73
+ userId: context.userId,
74
+ statusCode: response.status,
75
+ responseTime,
76
+ headers: logHeaders
77
+ ? this.sanitizeHeaders(response.headers, sanitizeHeaders)
78
+ : undefined,
79
+ body: logBody ? this.sanitizeBody(response.data) : undefined,
80
+ responseSize: JSON.stringify(response.data).length,
81
+ cacheHit,
82
+ circuitBreakerState,
83
+ };
84
+ const logMessage = `HTTP Response [${requestId}]: ${response.status} (${responseTime}ms)${cacheHit ? ' [CACHE HIT]' : ''}`;
85
+ switch ((loggingOptions || {}).logLevel) {
86
+ case 'debug':
87
+ this.logger.debug(logMessage, logData);
88
+ break;
89
+ case 'info':
90
+ default:
91
+ this.logger.log(logMessage, logData);
92
+ break;
93
+ }
94
+ if (databaseLogging && this.logRepository) {
95
+ const callInfo = this.extractCallInfo(decoratorContext, response.config);
96
+ this.saveToDatabase({
97
+ id: requestId,
98
+ requestId,
99
+ userId: context.userId,
100
+ method: ((_a = response.config.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'UNKNOWN',
101
+ url: response.config.url || '',
102
+ headers: this.sanitizeHeaders(response.config.headers, sanitizeHeaders),
103
+ body: this.sanitizeBodyAsString(response.config.data),
104
+ params: response.config.params,
105
+ statusCode: response.status,
106
+ responseTime,
107
+ attemptCount: (retryRecords === null || retryRecords === void 0 ? void 0 : retryRecords.length)
108
+ ? Math.max(...retryRecords.map((r) => r.attempt))
109
+ : 1,
110
+ success: true,
111
+ responseHeaders: this.sanitizeHeaders(response.headers, sanitizeHeaders),
112
+ responseBody: logBody
113
+ ? this.sanitizeBodyAsString(response.data)
114
+ : undefined,
115
+ responseSize: JSON.stringify(response.data).length,
116
+ requestSize: JSON.stringify(response.config.data).length,
117
+ serviceName: context.appId,
118
+ operationName: callInfo.operationName,
119
+ clientIp: context.clientIp,
120
+ source: (_b = context.metadata) === null || _b === void 0 ? void 0 : _b.source,
121
+ tags: context.tags,
122
+ metadata: logData,
123
+ retryRecords,
124
+ cacheHit,
125
+ circuitBreakerState,
126
+ });
127
+ }
128
+ }
129
+ logRequestError(error, startTime, requestId, attemptCount, loggingOptions, databaseLogging = false, retryRecords, cacheHit, circuitBreakerState, decoratorContext) {
130
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
131
+ const { logHeaders = true, sanitizeHeaders = [] } = loggingOptions;
132
+ const responseTime = Date.now() - startTime;
133
+ const context = context_extractor_util_1.ContextExtractor.getHttpContext();
134
+ const logData = {
135
+ requestId,
136
+ userId: context.userId,
137
+ attemptCount,
138
+ responseTime,
139
+ message: error.message,
140
+ code: error.code,
141
+ errorCode: error.code,
142
+ statusCode: (_a = error.response) === null || _a === void 0 ? void 0 : _a.status,
143
+ headers: ((_b = error.config) === null || _b === void 0 ? void 0 : _b.headers) && logHeaders
144
+ ? this.sanitizeHeaders(error.config.headers, sanitizeHeaders)
145
+ : undefined,
146
+ circuitBreakerState,
147
+ };
148
+ const logMessage = `HTTP Error [${requestId}]: ${error.message} (${responseTime}ms)${circuitBreakerState ? ` [${circuitBreakerState}]` : ''}`;
149
+ switch ((loggingOptions || {}).logLevel) {
150
+ case 'debug':
151
+ this.logger.debug(logMessage, logData);
152
+ break;
153
+ case 'warn':
154
+ this.logger.warn(logMessage, logData);
155
+ break;
156
+ case 'error':
157
+ this.logger.error(logMessage, logData);
158
+ break;
159
+ default:
160
+ this.logger.error(logMessage, logData);
161
+ break;
162
+ }
163
+ if (databaseLogging && this.logRepository) {
164
+ const callInfo = this.extractCallInfo(decoratorContext, error.config);
165
+ this.saveToDatabase({
166
+ id: requestId,
167
+ requestId,
168
+ userId: context.userId,
169
+ method: ((_d = (_c = error.config) === null || _c === void 0 ? void 0 : _c.method) === null || _d === void 0 ? void 0 : _d.toUpperCase()) || 'UNKNOWN',
170
+ url: ((_e = error.config) === null || _e === void 0 ? void 0 : _e.url) || '',
171
+ headers: ((_f = error.config) === null || _f === void 0 ? void 0 : _f.headers)
172
+ ? this.sanitizeHeaders(error.config.headers, sanitizeHeaders)
173
+ : {},
174
+ body: this.sanitizeBodyAsString((_g = error.config) === null || _g === void 0 ? void 0 : _g.data),
175
+ params: (_h = error.config) === null || _h === void 0 ? void 0 : _h.params,
176
+ statusCode: (_j = error.response) === null || _j === void 0 ? void 0 : _j.status,
177
+ responseTime,
178
+ attemptCount,
179
+ success: false,
180
+ errorMessage: error.message,
181
+ errorStack: error.stack,
182
+ errorCode: error.code,
183
+ requestSize: JSON.stringify(((_k = error.config) === null || _k === void 0 ? void 0 : _k.data) || {}).length,
184
+ serviceName: context.appId,
185
+ operationName: callInfo.operationName,
186
+ clientIp: context.clientIp,
187
+ source: (_l = context.metadata) === null || _l === void 0 ? void 0 : _l.source,
188
+ tags: context.tags,
189
+ metadata: logData,
190
+ retryRecords,
191
+ cacheHit,
192
+ circuitBreakerState,
193
+ });
194
+ }
195
+ }
196
+ findLogs(options) {
197
+ return __awaiter(this, void 0, void 0, function* () {
198
+ if (!this.logRepository) {
199
+ throw new Error('Database logging not available');
200
+ }
201
+ const queryBuilder = this.logRepository.createQueryBuilder('log');
202
+ if (options.requestId) {
203
+ queryBuilder.andWhere('log.requestId = :requestId', {
204
+ requestId: options.requestId,
205
+ });
206
+ }
207
+ if (options.userId) {
208
+ queryBuilder.andWhere('log.userId = :userId', { userId: options.userId });
209
+ }
210
+ if (options.method) {
211
+ queryBuilder.andWhere('log.method = :method', { method: options.method });
212
+ }
213
+ if (options.url) {
214
+ queryBuilder.andWhere('log.url LIKE :url', { url: `%${options.url}%` });
215
+ }
216
+ if (options.statusCode) {
217
+ queryBuilder.andWhere('log.statusCode = :statusCode', {
218
+ statusCode: options.statusCode,
219
+ });
220
+ }
221
+ if (options.success !== undefined) {
222
+ queryBuilder.andWhere('log.success = :success', {
223
+ success: options.success,
224
+ });
225
+ }
226
+ if (options.startDate) {
227
+ queryBuilder.andWhere('log.createdAt >= :startDate', {
228
+ startDate: options.startDate,
229
+ });
230
+ }
231
+ if (options.endDate) {
232
+ queryBuilder.andWhere('log.createdAt <= :endDate', {
233
+ endDate: options.endDate,
234
+ });
235
+ }
236
+ queryBuilder.orderBy('log.createdAt', 'DESC');
237
+ if (options.limit) {
238
+ queryBuilder.limit(options.limit);
239
+ }
240
+ if (options.offset) {
241
+ queryBuilder.offset(options.offset);
242
+ }
243
+ return queryBuilder.getMany();
244
+ });
245
+ }
246
+ getStatistics(options) {
247
+ return __awaiter(this, void 0, void 0, function* () {
248
+ if (!this.logRepository) {
249
+ throw new Error('Database logging not available');
250
+ }
251
+ const queryBuilder = this.logRepository.createQueryBuilder('log');
252
+ if (options.startDate) {
253
+ queryBuilder.andWhere('log.createdAt >= :startDate', {
254
+ startDate: options.startDate,
255
+ });
256
+ }
257
+ if (options.endDate) {
258
+ queryBuilder.andWhere('log.createdAt <= :endDate', {
259
+ endDate: options.endDate,
260
+ });
261
+ }
262
+ if (options.userId) {
263
+ queryBuilder.andWhere('log.userId = :userId', { userId: options.userId });
264
+ }
265
+ const total = yield queryBuilder.getCount();
266
+ const success = yield queryBuilder
267
+ .clone()
268
+ .andWhere('log.success = :success', { success: true })
269
+ .getCount();
270
+ const failed = total - success;
271
+ const avgResponseTime = yield queryBuilder
272
+ .clone()
273
+ .select('AVG(log.responseTime)', 'avg')
274
+ .getRawOne();
275
+ const statusStats = yield queryBuilder
276
+ .clone()
277
+ .select('log.statusCode', 'statusCode')
278
+ .addSelect('COUNT(*)', 'count')
279
+ .groupBy('log.statusCode')
280
+ .getRawMany();
281
+ const methodStats = yield queryBuilder
282
+ .clone()
283
+ .select('log.method', 'method')
284
+ .addSelect('COUNT(*)', 'count')
285
+ .groupBy('log.method')
286
+ .getRawMany();
287
+ return {
288
+ total,
289
+ success,
290
+ failed,
291
+ successRate: total > 0 ? (success / total) * 100 : 0,
292
+ averageResponseTime: (avgResponseTime === null || avgResponseTime === void 0 ? void 0 : avgResponseTime.avg) || 0,
293
+ statusStats: statusStats.reduce((acc, item) => {
294
+ acc[item.statusCode] = parseInt(item.count);
295
+ return acc;
296
+ }, {}),
297
+ methodStats: methodStats.reduce((acc, item) => {
298
+ acc[item.method] = parseInt(item.count);
299
+ return acc;
300
+ }, {}),
301
+ };
302
+ });
303
+ }
304
+ initializeDatabaseLogging() {
305
+ return __awaiter(this, void 0, void 0, function* () {
306
+ try {
307
+ this.logRepository = this.dataSource.getRepository(http_log_entity_1.HttpLogEntity);
308
+ this.logger.log('Database logging initialized');
309
+ }
310
+ catch (error) {
311
+ this.logger.error('Failed to initialize database logging', error);
312
+ }
313
+ });
314
+ }
315
+ extractCallInfo(decoratorContext, config) {
316
+ if (decoratorContext) {
317
+ const decoratorInfo = call_stack_extractor_util_1.CallStackExtractor.extractFromDecorator(decoratorContext.target, decoratorContext.propertyKey);
318
+ if (decoratorInfo.serviceClass && decoratorInfo.methodName) {
319
+ return {
320
+ operationName: decoratorInfo.operationName,
321
+ };
322
+ }
323
+ }
324
+ const manualInfo = call_stack_extractor_util_1.CallStackExtractor.getManualCallInfo();
325
+ if (manualInfo) {
326
+ return {
327
+ operationName: manualInfo.operationName,
328
+ };
329
+ }
330
+ const stackInfo = call_stack_extractor_util_1.CallStackExtractor.getCallInfo();
331
+ if (stackInfo.serviceClass && stackInfo.methodName) {
332
+ return {
333
+ operationName: stackInfo.operationName,
334
+ };
335
+ }
336
+ if (config === null || config === void 0 ? void 0 : config.url) {
337
+ const pathParts = config.url
338
+ .split('/')
339
+ .filter((part) => part && !part.includes('{'));
340
+ if (pathParts.length > 0) {
341
+ const operation = pathParts[pathParts.length - 1];
342
+ return {
343
+ operationName: operation,
344
+ };
345
+ }
346
+ }
347
+ return {};
348
+ }
349
+ saveToDatabase(logEntity) {
350
+ return __awaiter(this, void 0, void 0, function* () {
351
+ if (!this.logRepository)
352
+ return;
353
+ try {
354
+ yield this.logRepository.save(logEntity);
355
+ }
356
+ catch (error) {
357
+ this.logger.error('Failed to save HTTP log to database', error);
358
+ }
359
+ });
360
+ }
361
+ sanitizeBodyAsString(data) {
362
+ if (!data)
363
+ return undefined;
364
+ if (typeof data === 'string') {
365
+ return data.length > 5000 ? data.substring(0, 5000) + '...' : data;
366
+ }
367
+ const jsonString = JSON.stringify(data);
368
+ return jsonString.length > 5000
369
+ ? jsonString.substring(0, 5000) + '...'
370
+ : jsonString;
371
+ }
372
+ sanitizeHeaders(headers, sanitizeHeaders) {
373
+ if (!headers)
374
+ return {};
375
+ const sanitized = {};
376
+ const defaultSensitiveHeaders = [
377
+ 'authorization',
378
+ 'apikey',
379
+ 'password',
380
+ 'token',
381
+ 'secret',
382
+ 'cookie',
383
+ 'set-cookie',
384
+ 'x-api-key',
385
+ 'x-auth-token',
386
+ ];
387
+ const headersToSanitize = [...defaultSensitiveHeaders, ...sanitizeHeaders];
388
+ Object.keys(headers).forEach((key) => {
389
+ if (headersToSanitize.some((sensitive) => key.toLowerCase().includes(sensitive.toLowerCase()))) {
390
+ sanitized[key] = '[FILTERED]';
391
+ }
392
+ else {
393
+ sanitized[key] = String(headers[key]);
394
+ }
395
+ });
396
+ return sanitized;
397
+ }
398
+ sanitizeBody(body) {
399
+ if (!body)
400
+ return undefined;
401
+ if (typeof body === 'string') {
402
+ try {
403
+ body = JSON.parse(body);
404
+ }
405
+ catch (_a) {
406
+ return body.length > 1000 ? body.substring(0, 1000) + '...' : body;
407
+ }
408
+ }
409
+ if (typeof body === 'object') {
410
+ const sanitized = Object.assign({}, body);
411
+ const sensitiveFields = [
412
+ 'password',
413
+ 'secret',
414
+ 'token',
415
+ 'key',
416
+ 'authorization',
417
+ 'credential',
418
+ 'private',
419
+ 'confidential',
420
+ 'ssn',
421
+ 'creditCard',
422
+ ];
423
+ this.sanitizeObject(sanitized, sensitiveFields);
424
+ return sanitized;
425
+ }
426
+ return body;
427
+ }
428
+ sanitizeObject(obj, sensitiveFields) {
429
+ if (typeof obj !== 'object' || obj === null)
430
+ return;
431
+ for (const key in obj) {
432
+ if (sensitiveFields.some((field) => key.toLowerCase().includes(field.toLowerCase()))) {
433
+ obj[key] = '[FILTERED]';
434
+ }
435
+ else if (typeof obj[key] === 'object') {
436
+ this.sanitizeObject(obj[key], sensitiveFields);
437
+ }
438
+ }
439
+ }
440
+ };
441
+ exports.HttpLoggingService = HttpLoggingService;
442
+ exports.HttpLoggingService = HttpLoggingService = HttpLoggingService_1 = __decorate([
443
+ (0, common_1.Injectable)(),
444
+ __metadata("design:paramtypes", [typeorm_1.DataSource])
445
+ ], HttpLoggingService);
@@ -0,0 +1,29 @@
1
+ export declare class CallStackExtractor {
2
+ static extractCallInfo(): {
3
+ serviceClass?: string;
4
+ methodName?: string;
5
+ operationName?: string;
6
+ };
7
+ static setCallInfo(serviceClass: string, methodName: string, operationName?: string): void;
8
+ static getManualCallInfo(): {
9
+ serviceClass?: string;
10
+ methodName?: string;
11
+ operationName?: string;
12
+ } | null;
13
+ static clearCallInfo(): void;
14
+ static getCallInfo(): {
15
+ serviceClass?: string;
16
+ methodName?: string;
17
+ operationName?: string;
18
+ };
19
+ static extractFromDecorator(target: any, propertyKey: string): {
20
+ serviceClass?: string;
21
+ methodName?: string;
22
+ operationName?: string;
23
+ };
24
+ static generateOperationName(serviceClass?: string, methodName?: string, config?: any): string;
25
+ static formatServiceClass(serviceClass?: string): string;
26
+ static formatMethodName(methodName?: string): string;
27
+ private static parseStackLine;
28
+ private static isInternalCall;
29
+ }
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CallStackExtractor = void 0;
4
+ class CallStackExtractor {
5
+ static extractCallInfo() {
6
+ const stack = new Error().stack;
7
+ if (!stack) {
8
+ return {};
9
+ }
10
+ const lines = stack.split('\n');
11
+ const httpClientIndex = lines.findIndex((line) => line.includes('http-client.service.ts') ||
12
+ line.includes('HttpClientService'));
13
+ if (httpClientIndex === -1) {
14
+ return {};
15
+ }
16
+ for (let i = httpClientIndex + 1; i < lines.length; i++) {
17
+ const line = lines[i];
18
+ const callInfo = this.parseStackLine(line);
19
+ if (callInfo && !this.isInternalCall(callInfo.serviceClass)) {
20
+ return callInfo;
21
+ }
22
+ }
23
+ return {};
24
+ }
25
+ static setCallInfo(serviceClass, methodName, operationName) {
26
+ if (typeof global !== 'undefined') {
27
+ global.httpCallContext = {
28
+ serviceClass,
29
+ methodName,
30
+ operationName: operationName || `${serviceClass}.${methodName}`,
31
+ timestamp: Date.now(),
32
+ };
33
+ }
34
+ }
35
+ static getManualCallInfo() {
36
+ if (typeof global !== 'undefined' && global.httpCallContext) {
37
+ const context = global.httpCallContext;
38
+ if (Date.now() - context.timestamp < 1000) {
39
+ return {
40
+ serviceClass: context.serviceClass,
41
+ methodName: context.methodName,
42
+ operationName: context.operationName,
43
+ };
44
+ }
45
+ delete global.httpCallContext;
46
+ }
47
+ return null;
48
+ }
49
+ static clearCallInfo() {
50
+ if (typeof global !== 'undefined' && global.httpCallContext) {
51
+ delete global.httpCallContext;
52
+ }
53
+ }
54
+ static getCallInfo() {
55
+ const manualInfo = this.getManualCallInfo();
56
+ if (manualInfo) {
57
+ return manualInfo;
58
+ }
59
+ return this.extractCallInfo();
60
+ }
61
+ static extractFromDecorator(target, propertyKey) {
62
+ var _a;
63
+ const serviceClass = (_a = target.constructor) === null || _a === void 0 ? void 0 : _a.name;
64
+ const methodName = propertyKey;
65
+ return {
66
+ serviceClass,
67
+ methodName,
68
+ operationName: serviceClass && methodName
69
+ ? `${serviceClass}.${methodName}`
70
+ : undefined,
71
+ };
72
+ }
73
+ static generateOperationName(serviceClass, methodName, config) {
74
+ if (!serviceClass || !methodName) {
75
+ return 'Unknown';
76
+ }
77
+ let operationName = `${serviceClass}.${methodName}`;
78
+ if (config === null || config === void 0 ? void 0 : config.url) {
79
+ const url = config.url;
80
+ const pathParts = url
81
+ .split('/')
82
+ .filter((part) => part && !part.includes('{'));
83
+ if (pathParts.length > 0) {
84
+ const lastPart = pathParts[pathParts.length - 1];
85
+ if (lastPart && lastPart !== 'api' && lastPart.length < 50) {
86
+ operationName += `(${lastPart})`;
87
+ }
88
+ }
89
+ }
90
+ return operationName;
91
+ }
92
+ static formatServiceClass(serviceClass) {
93
+ if (!serviceClass)
94
+ return 'Unknown';
95
+ return serviceClass.replace(/Service|Controller|Provider|Handler$/, '');
96
+ }
97
+ static formatMethodName(methodName) {
98
+ if (!methodName)
99
+ return 'unknown';
100
+ return methodName
101
+ .replace(/([A-Z])/g, ' $1')
102
+ .replace(/^./, (str) => str.toUpperCase())
103
+ .trim();
104
+ }
105
+ static parseStackLine(line) {
106
+ const match = line.match(/at\s+([^.]+)\.([^(]+)\s*\(/);
107
+ if (!match) {
108
+ return null;
109
+ }
110
+ const [, serviceClass, methodName] = match;
111
+ return {
112
+ serviceClass,
113
+ methodName,
114
+ operationName: `${serviceClass}.${methodName}`,
115
+ };
116
+ }
117
+ static isInternalCall(serviceClass) {
118
+ if (!serviceClass)
119
+ return true;
120
+ const internalPatterns = [
121
+ /^Http/,
122
+ /^HttpClient/,
123
+ /^CircuitBreaker/,
124
+ /^Retry/,
125
+ /^Cache/,
126
+ /^Logger/,
127
+ /^Context/,
128
+ /Interceptor/,
129
+ /Middleware/,
130
+ /__/,
131
+ /^Array\./,
132
+ /^Object\./,
133
+ /^Function\./,
134
+ ];
135
+ return internalPatterns.some((pattern) => pattern.test(serviceClass));
136
+ }
137
+ }
138
+ exports.CallStackExtractor = CallStackExtractor;
@@ -0,0 +1,44 @@
1
+ export declare class ContextExtractor {
2
+ static getHttpContext(): {
3
+ requestId?: string;
4
+ userId?: string;
5
+ clientIp?: string;
6
+ userAgent?: string;
7
+ appId?: string;
8
+ metadata?: Record<string, any>;
9
+ tags?: string[];
10
+ };
11
+ static getRequestId(): string | undefined;
12
+ static getUserId(): string | undefined;
13
+ static getClientIp(): string | undefined;
14
+ static getUserAgent(): string | undefined;
15
+ static getServiceName(): string | undefined;
16
+ static getMetadata(): Record<string, any> | undefined;
17
+ static getTags(): string[];
18
+ static addTag(tag: string): void;
19
+ static getContextSummary(): {
20
+ requestId?: string;
21
+ userId?: string;
22
+ service?: string;
23
+ clientIp?: string;
24
+ hasUser: boolean;
25
+ requestSource: string;
26
+ };
27
+ static getRequestSource(): {
28
+ source: 'internal' | 'external' | 'unknown';
29
+ ip?: string;
30
+ userAgent?: string;
31
+ service?: string;
32
+ };
33
+ static isInternalRequest(): boolean;
34
+ static getSecurityContext(): {
35
+ isAuthenticated: boolean;
36
+ userId?: string;
37
+ tenantId?: string;
38
+ role?: string;
39
+ permissions: string[];
40
+ securityLevel: 'low' | 'medium' | 'high';
41
+ };
42
+ private static generateSpanId;
43
+ private static isInternal172IP;
44
+ }