@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,264 @@
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 HttpCacheService_1;
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.HttpCacheService = void 0;
23
+ const common_1 = require("@nestjs/common");
24
+ const cache_service_1 = require("../../cache/cache.service");
25
+ const cache_options_interface_1 = require("../../cache/interfaces/cache-options.interface");
26
+ let HttpCacheService = HttpCacheService_1 = class HttpCacheService {
27
+ constructor(cacheService) {
28
+ this.cacheService = cacheService;
29
+ this.logger = new common_1.Logger(HttpCacheService_1.name);
30
+ }
31
+ get(config, cacheOptions) {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ var _a;
34
+ const key = this.generateCacheKey(config, cacheOptions);
35
+ const cacheKey = this.buildCacheKey(cacheOptions, key);
36
+ try {
37
+ const cachedResponse = yield this.cacheService.get(cacheKey, {
38
+ layers: this.mapLayers((_a = cacheOptions.options) === null || _a === void 0 ? void 0 : _a.layers),
39
+ ttl: cacheOptions.defaultTtl,
40
+ });
41
+ if (cachedResponse) {
42
+ this.logger.debug(`Cache hit: ${cacheKey}`);
43
+ return cachedResponse;
44
+ }
45
+ this.logger.debug(`Cache miss: ${cacheKey}`);
46
+ return null;
47
+ }
48
+ catch (error) {
49
+ this.logger.warn(`Cache get error: ${error.message}`);
50
+ return null;
51
+ }
52
+ });
53
+ }
54
+ set(config, response, cacheOptions) {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ var _a, _b, _c, _d;
57
+ const key = this.generateCacheKey(config, cacheOptions);
58
+ const cacheKey = this.buildCacheKey(cacheOptions, key);
59
+ if (!this.isResponseCacheable(response, cacheOptions)) {
60
+ this.logger.debug(`Response not cacheable: ${response.status} ${config.url}`);
61
+ return;
62
+ }
63
+ try {
64
+ yield this.cacheService.set(cacheKey, response, {
65
+ layers: this.mapLayers((_a = cacheOptions.options) === null || _a === void 0 ? void 0 : _a.layers),
66
+ ttl: cacheOptions.defaultTtl,
67
+ namespace: ((_b = cacheOptions.options) === null || _b === void 0 ? void 0 : _b.prefix) || 'http',
68
+ condition: (_c = cacheOptions.options) === null || _c === void 0 ? void 0 : _c.condition,
69
+ backfill: (_d = cacheOptions.options) === null || _d === void 0 ? void 0 : _d.backfill,
70
+ });
71
+ this.logger.debug(`Response cached: ${cacheKey}`);
72
+ }
73
+ catch (error) {
74
+ this.logger.warn(`Cache set error: ${error.message}`);
75
+ }
76
+ });
77
+ }
78
+ clear(pattern) {
79
+ return __awaiter(this, void 0, void 0, function* () {
80
+ try {
81
+ if (pattern) {
82
+ yield this.cacheService.deletePattern(pattern);
83
+ this.logger.debug(`Cache cleared with pattern: ${pattern}`);
84
+ }
85
+ else {
86
+ yield this.cacheService.deletePattern('http:*');
87
+ this.logger.debug('All HTTP cache cleared');
88
+ }
89
+ }
90
+ catch (error) {
91
+ this.logger.warn(`Cache clear error: ${error.message}`);
92
+ }
93
+ });
94
+ }
95
+ getStats() {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ try {
98
+ const stats = this.cacheService.getStats();
99
+ return stats;
100
+ }
101
+ catch (error) {
102
+ this.logger.warn(`Get cache stats error: ${error.message}`);
103
+ return null;
104
+ }
105
+ });
106
+ }
107
+ cleanup() {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ try {
110
+ yield this.cacheService.deletePattern('http:*');
111
+ this.logger.debug('HTTP cache cleanup completed');
112
+ }
113
+ catch (error) {
114
+ this.logger.warn(`Cache cleanup error: ${error.message}`);
115
+ }
116
+ });
117
+ }
118
+ warmup(urls, headers) {
119
+ return __awaiter(this, void 0, void 0, function* () {
120
+ this.logger.log(`Starting cache warmup for ${urls.length} URLs`);
121
+ this.logger.log('Cache warmup completed');
122
+ });
123
+ }
124
+ getDetailedStats() {
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ try {
127
+ const stats = yield this.getStats();
128
+ const recentHits = yield this.getRecentCacheActivity();
129
+ return Object.assign(Object.assign({}, stats), { recentActivity: recentHits, recommendations: this.generateRecommendations(stats) });
130
+ }
131
+ catch (error) {
132
+ this.logger.warn(`Get detailed cache stats error: ${error.message}`);
133
+ return null;
134
+ }
135
+ });
136
+ }
137
+ generateCacheKey(config, cacheOptions) {
138
+ var _a;
139
+ if (cacheOptions.keyGenerator) {
140
+ return cacheOptions.keyGenerator(config);
141
+ }
142
+ const keyData = {
143
+ method: (_a = config.method) === null || _a === void 0 ? void 0 : _a.toLowerCase(),
144
+ url: config.url,
145
+ params: config.params,
146
+ data: config.data,
147
+ headers: this.selectHeadersForCacheKey(config.headers),
148
+ };
149
+ return this.hashObject(keyData);
150
+ }
151
+ buildCacheKey(cacheOptions, key) {
152
+ var _a;
153
+ const namespace = ((_a = cacheOptions.options) === null || _a === void 0 ? void 0 : _a.prefix) || 'http';
154
+ return `${namespace}:${key}`;
155
+ }
156
+ mapLayers(layers) {
157
+ if (!layers || layers.length === 0) {
158
+ return [cache_options_interface_1.CacheLayer.MEMORY, cache_options_interface_1.CacheLayer.REDIS];
159
+ }
160
+ return layers.map((layer) => {
161
+ switch (layer) {
162
+ case 'cls':
163
+ return cache_options_interface_1.CacheLayer.CLS;
164
+ case 'memory':
165
+ return cache_options_interface_1.CacheLayer.MEMORY;
166
+ case 'redis':
167
+ return cache_options_interface_1.CacheLayer.REDIS;
168
+ default:
169
+ return cache_options_interface_1.CacheLayer.MEMORY;
170
+ }
171
+ });
172
+ }
173
+ selectHeadersForCacheKey(headers) {
174
+ if (!headers)
175
+ return {};
176
+ const cacheKeyHeaders = [
177
+ 'accept',
178
+ 'accept-language',
179
+ 'accept-encoding',
180
+ 'content-type',
181
+ 'authorization',
182
+ ];
183
+ const selectedHeaders = {};
184
+ cacheKeyHeaders.forEach((key) => {
185
+ if (headers[key]) {
186
+ selectedHeaders[key] = headers[key];
187
+ }
188
+ });
189
+ return selectedHeaders;
190
+ }
191
+ isResponseCacheable(response, config) {
192
+ var _a;
193
+ if (!config.cacheableStatusCodes.includes(response.status)) {
194
+ return false;
195
+ }
196
+ const method = (_a = response.config.method) === null || _a === void 0 ? void 0 : _a.toLowerCase();
197
+ if (!config.cacheableMethods.includes(method || 'get')) {
198
+ return false;
199
+ }
200
+ const cacheControl = response.headers['cache-control'];
201
+ if (cacheControl) {
202
+ if (cacheControl.includes('no-store') ||
203
+ cacheControl.includes('no-cache')) {
204
+ return false;
205
+ }
206
+ if (cacheControl.includes('private')) {
207
+ this.logger.debug('Private cache detected, caching with caution');
208
+ }
209
+ }
210
+ if (response.data) {
211
+ const responseSize = JSON.stringify(response.data).length;
212
+ if (responseSize > 1024 * 1024) {
213
+ this.logger.warn(`Response too large for caching: ${responseSize} bytes`);
214
+ return false;
215
+ }
216
+ }
217
+ return true;
218
+ }
219
+ hashObject(obj) {
220
+ const str = JSON.stringify(obj, Object.keys(obj).sort());
221
+ let hash = 0;
222
+ for (let i = 0; i < str.length; i++) {
223
+ const char = str.charCodeAt(i);
224
+ hash = (hash << 5) - hash + char;
225
+ hash = hash & hash;
226
+ }
227
+ return Math.abs(hash).toString(36);
228
+ }
229
+ calculateHitRate(...stats) {
230
+ let totalHits = 0;
231
+ let totalRequests = 0;
232
+ stats.forEach((stat) => {
233
+ if (stat) {
234
+ totalHits += stat.hits || 0;
235
+ totalRequests += (stat.hits || 0) + (stat.misses || 0);
236
+ }
237
+ });
238
+ return totalRequests > 0 ? (totalHits / totalRequests) * 100 : 0;
239
+ }
240
+ getRecentCacheActivity() {
241
+ return __awaiter(this, void 0, void 0, function* () {
242
+ return {
243
+ recentHits: 0,
244
+ recentMisses: 0,
245
+ topCacheKeys: [],
246
+ };
247
+ });
248
+ }
249
+ generateRecommendations(stats) {
250
+ const recommendations = [];
251
+ if (stats.combined.hitRate < 50) {
252
+ recommendations.push('Cache hit rate is low, consider increasing TTL or optimizing cache keys');
253
+ }
254
+ if (stats.redis.memoryUsage > 0.8) {
255
+ recommendations.push('Redis memory usage is high, consider increasing memory or cleaning up old cache entries');
256
+ }
257
+ return recommendations;
258
+ }
259
+ };
260
+ exports.HttpCacheService = HttpCacheService;
261
+ exports.HttpCacheService = HttpCacheService = HttpCacheService_1 = __decorate([
262
+ (0, common_1.Injectable)(),
263
+ __metadata("design:paramtypes", [cache_service_1.CacheService])
264
+ ], HttpCacheService);
@@ -0,0 +1,33 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import { CircuitBreakerConfig } from '../interfaces/http-client-config.interface';
3
+ export declare class HttpCircuitBreakerService {
4
+ private readonly logger;
5
+ private readonly circuitBreakers;
6
+ getCircuitBreaker(key: string, config: CircuitBreakerConfig): CircuitBreaker;
7
+ executeWithCircuitBreaker<T>(key: string, requestFn: () => Promise<T>, config: CircuitBreakerConfig): Promise<T>;
8
+ resetAll(): void;
9
+ getAllStates(): Record<string, any>;
10
+ }
11
+ declare class CircuitBreaker {
12
+ private readonly key;
13
+ private readonly config;
14
+ private readonly logger;
15
+ private state;
16
+ private failureCount;
17
+ private successCount;
18
+ private lastFailureTime;
19
+ private nextAttemptTime;
20
+ private requestCount;
21
+ private windowStartTime;
22
+ constructor(key: string, config: CircuitBreakerConfig, logger: Logger);
23
+ execute<T>(requestFn: () => Promise<T>): Promise<T>;
24
+ reset(): void;
25
+ getState(): any;
26
+ private onSuccess;
27
+ private onFailure;
28
+ private transitionToClosed;
29
+ private transitionToOpen;
30
+ private transitionToHalfOpen;
31
+ private resetMonitoringWindow;
32
+ }
33
+ export {};
@@ -0,0 +1,180 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
9
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
10
+ return new (P || (P = Promise))(function (resolve, reject) {
11
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
13
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
14
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
15
+ });
16
+ };
17
+ var HttpCircuitBreakerService_1;
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.HttpCircuitBreakerService = void 0;
20
+ const common_1 = require("@nestjs/common");
21
+ var CircuitBreakerState;
22
+ (function (CircuitBreakerState) {
23
+ CircuitBreakerState["CLOSED"] = "CLOSED";
24
+ CircuitBreakerState["OPEN"] = "OPEN";
25
+ CircuitBreakerState["HALF_OPEN"] = "HALF_OPEN";
26
+ })(CircuitBreakerState || (CircuitBreakerState = {}));
27
+ let HttpCircuitBreakerService = HttpCircuitBreakerService_1 = class HttpCircuitBreakerService {
28
+ constructor() {
29
+ this.logger = new common_1.Logger(HttpCircuitBreakerService_1.name);
30
+ this.circuitBreakers = new Map();
31
+ }
32
+ getCircuitBreaker(key, config) {
33
+ if (!this.circuitBreakers.has(key)) {
34
+ this.circuitBreakers.set(key, new CircuitBreaker(key, config, this.logger));
35
+ }
36
+ return this.circuitBreakers.get(key);
37
+ }
38
+ executeWithCircuitBreaker(key, requestFn, config) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ const circuitBreaker = this.getCircuitBreaker(key, config);
41
+ return circuitBreaker.execute(requestFn);
42
+ });
43
+ }
44
+ resetAll() {
45
+ this.circuitBreakers.forEach((cb) => cb.reset());
46
+ }
47
+ getAllStates() {
48
+ const states = {};
49
+ this.circuitBreakers.forEach((cb, key) => {
50
+ states[key] = cb.getState();
51
+ });
52
+ return states;
53
+ }
54
+ };
55
+ exports.HttpCircuitBreakerService = HttpCircuitBreakerService;
56
+ exports.HttpCircuitBreakerService = HttpCircuitBreakerService = HttpCircuitBreakerService_1 = __decorate([
57
+ (0, common_1.Injectable)()
58
+ ], HttpCircuitBreakerService);
59
+ class CircuitBreaker {
60
+ constructor(key, config, logger) {
61
+ this.key = key;
62
+ this.config = config;
63
+ this.logger = logger;
64
+ this.state = CircuitBreakerState.CLOSED;
65
+ this.failureCount = 0;
66
+ this.successCount = 0;
67
+ this.lastFailureTime = 0;
68
+ this.nextAttemptTime = 0;
69
+ this.requestCount = 0;
70
+ this.windowStartTime = Date.now();
71
+ }
72
+ execute(requestFn) {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ const currentTime = Date.now();
75
+ if (currentTime - this.windowStartTime > this.config.monitoringPeriodMs) {
76
+ this.resetMonitoringWindow();
77
+ }
78
+ switch (this.state) {
79
+ case CircuitBreakerState.OPEN:
80
+ if (currentTime < this.nextAttemptTime) {
81
+ throw new Error(`Circuit breaker is OPEN for ${this.key}. Next attempt at ${new Date(this.nextAttemptTime)}`);
82
+ }
83
+ this.transitionToHalfOpen();
84
+ break;
85
+ case CircuitBreakerState.HALF_OPEN:
86
+ this.logger.debug(`Circuit breaker is HALF_OPEN for ${this.key}, attempting request`);
87
+ break;
88
+ case CircuitBreakerState.CLOSED:
89
+ default:
90
+ break;
91
+ }
92
+ this.requestCount++;
93
+ try {
94
+ const result = yield requestFn();
95
+ this.onSuccess();
96
+ return result;
97
+ }
98
+ catch (error) {
99
+ this.onFailure();
100
+ throw error;
101
+ }
102
+ });
103
+ }
104
+ reset() {
105
+ this.transitionToClosed();
106
+ this.resetMonitoringWindow();
107
+ }
108
+ getState() {
109
+ return {
110
+ state: this.state,
111
+ failureCount: this.failureCount,
112
+ successCount: this.successCount,
113
+ requestCount: this.requestCount,
114
+ lastFailureTime: this.lastFailureTime,
115
+ nextAttemptTime: this.nextAttemptTime,
116
+ windowStartTime: this.windowStartTime,
117
+ config: this.config,
118
+ };
119
+ }
120
+ onSuccess() {
121
+ this.failureCount = 0;
122
+ switch (this.state) {
123
+ case CircuitBreakerState.HALF_OPEN:
124
+ this.successCount++;
125
+ if (this.successCount >= (this.config.countHalfOpenCalls ? 3 : 1)) {
126
+ this.transitionToClosed();
127
+ }
128
+ break;
129
+ case CircuitBreakerState.CLOSED:
130
+ default:
131
+ break;
132
+ }
133
+ }
134
+ onFailure() {
135
+ this.failureCount++;
136
+ this.lastFailureTime = Date.now();
137
+ switch (this.state) {
138
+ case CircuitBreakerState.HALF_OPEN:
139
+ this.transitionToOpen();
140
+ break;
141
+ case CircuitBreakerState.CLOSED:
142
+ if (this.requestCount >= this.config.minimumThroughputThreshold &&
143
+ this.failureCount >= this.config.failureThreshold) {
144
+ this.transitionToOpen();
145
+ }
146
+ break;
147
+ default:
148
+ break;
149
+ }
150
+ }
151
+ transitionToClosed() {
152
+ if (this.state !== CircuitBreakerState.CLOSED) {
153
+ this.logger.log(`Circuit breaker ${this.key} transitioned to CLOSED`);
154
+ this.state = CircuitBreakerState.CLOSED;
155
+ this.failureCount = 0;
156
+ this.successCount = 0;
157
+ }
158
+ }
159
+ transitionToOpen() {
160
+ if (this.state !== CircuitBreakerState.OPEN) {
161
+ this.logger.warn(`Circuit breaker ${this.key} transitioned to OPEN due to ${this.failureCount} failures`);
162
+ this.state = CircuitBreakerState.OPEN;
163
+ this.nextAttemptTime = Date.now() + this.config.recoveryTimeoutMs;
164
+ this.successCount = 0;
165
+ }
166
+ }
167
+ transitionToHalfOpen() {
168
+ if (this.state !== CircuitBreakerState.HALF_OPEN) {
169
+ this.logger.log(`Circuit breaker ${this.key} transitioned to HALF_OPEN`);
170
+ this.state = CircuitBreakerState.HALF_OPEN;
171
+ this.successCount = 0;
172
+ }
173
+ }
174
+ resetMonitoringWindow() {
175
+ this.windowStartTime = Date.now();
176
+ this.requestCount = 0;
177
+ this.failureCount = 0;
178
+ this.logger.debug(`Reset monitoring window for circuit breaker ${this.key}`);
179
+ }
180
+ }
@@ -0,0 +1,43 @@
1
+ import { AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ import { HttpClientConfig } from '../interfaces/http-client-config.interface';
3
+ import { HttpCircuitBreakerService } from './circuit-breaker.service';
4
+ import { HttpLoggingService } from './logging.service';
5
+ import { HttpCacheService } from './cache.service';
6
+ interface ExtendedAxiosRequestConfig extends AxiosRequestConfig {
7
+ metadata?: {
8
+ requestId?: string;
9
+ startTime?: number;
10
+ [key: string]: any;
11
+ };
12
+ }
13
+ export declare class HttpClientService {
14
+ private readonly circuitBreakerService;
15
+ private readonly loggingService;
16
+ private readonly cacheService;
17
+ private readonly logger;
18
+ private readonly axiosInstance;
19
+ private readonly defaultConfig;
20
+ private requestStats;
21
+ constructor(circuitBreakerService: HttpCircuitBreakerService, loggingService: HttpLoggingService, cacheService: HttpCacheService, config?: HttpClientConfig);
22
+ request<T = any>(config: ExtendedAxiosRequestConfig, decoratorContext?: any): Promise<T>;
23
+ generateCurlCommand(config: ExtendedAxiosRequestConfig): string;
24
+ generateDebugCurlCommand(config: ExtendedAxiosRequestConfig, response?: AxiosResponse): string;
25
+ getStats(): any;
26
+ resetStats(): void;
27
+ get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
28
+ post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
29
+ put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
30
+ patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
31
+ delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
32
+ private createAxiosInstance;
33
+ private executeWithFeatures;
34
+ private calculateRetryDelay;
35
+ private applyDecoratorConfig;
36
+ private shouldCacheRequest;
37
+ private generateCircuitBreakerKey;
38
+ private updateStats;
39
+ private updateErrorStats;
40
+ private mergeWithDefaults;
41
+ private deepMerge;
42
+ }
43
+ export {};