@nest-omni/core 3.1.2-6 → 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.
- package/common/dto/dto-extensions.js +6 -5
- package/common/utils.d.ts +1 -0
- package/common/utils.js +6 -0
- package/http-client/config/http-client.config.d.ts +6 -0
- package/http-client/config/http-client.config.js +87 -0
- package/http-client/config/index.d.ts +1 -0
- package/http-client/config/index.js +17 -0
- package/http-client/decorators/http-client.decorators.d.ts +72 -0
- package/http-client/decorators/http-client.decorators.js +204 -0
- package/http-client/decorators/index.d.ts +1 -0
- package/http-client/decorators/index.js +17 -0
- package/http-client/entities/http-log.entity.d.ts +98 -0
- package/http-client/entities/http-log.entity.js +143 -0
- package/http-client/entities/index.d.ts +1 -0
- package/http-client/entities/index.js +17 -0
- package/http-client/errors/http-client.errors.d.ts +56 -0
- package/http-client/errors/http-client.errors.js +149 -0
- package/http-client/errors/index.d.ts +1 -0
- package/http-client/errors/index.js +17 -0
- package/http-client/examples/advanced-usage.example.d.ts +23 -0
- package/http-client/examples/advanced-usage.example.js +319 -0
- package/http-client/examples/basic-usage.example.d.ts +61 -0
- package/http-client/examples/basic-usage.example.js +171 -0
- package/http-client/examples/index.d.ts +3 -0
- package/http-client/examples/index.js +19 -0
- package/http-client/examples/multi-api-configuration.example.d.ts +98 -0
- package/http-client/examples/multi-api-configuration.example.js +353 -0
- package/http-client/http-client.module.d.ts +11 -0
- package/http-client/http-client.module.js +254 -0
- package/http-client/index.d.ts +10 -0
- package/http-client/index.js +27 -0
- package/http-client/interfaces/api-client-config.interface.d.ts +152 -0
- package/http-client/interfaces/api-client-config.interface.js +12 -0
- package/http-client/interfaces/http-client-config.interface.d.ts +123 -0
- package/http-client/interfaces/http-client-config.interface.js +2 -0
- package/http-client/services/api-client-registry.service.d.ts +40 -0
- package/http-client/services/api-client-registry.service.js +411 -0
- package/http-client/services/cache.service.d.ts +24 -0
- package/http-client/services/cache.service.js +264 -0
- package/http-client/services/circuit-breaker.service.d.ts +33 -0
- package/http-client/services/circuit-breaker.service.js +180 -0
- package/http-client/services/http-client.service.d.ts +43 -0
- package/http-client/services/http-client.service.js +384 -0
- package/http-client/services/http-log-query.service.d.ts +56 -0
- package/http-client/services/http-log-query.service.js +414 -0
- package/http-client/services/index.d.ts +7 -0
- package/http-client/services/index.js +23 -0
- package/http-client/services/log-cleanup.service.d.ts +64 -0
- package/http-client/services/log-cleanup.service.js +268 -0
- package/http-client/services/logging.service.d.ts +36 -0
- package/http-client/services/logging.service.js +445 -0
- package/http-client/utils/call-stack-extractor.util.d.ts +29 -0
- package/http-client/utils/call-stack-extractor.util.js +138 -0
- package/http-client/utils/context-extractor.util.d.ts +44 -0
- package/http-client/utils/context-extractor.util.js +173 -0
- package/http-client/utils/curl-generator.util.d.ts +9 -0
- package/http-client/utils/curl-generator.util.js +169 -0
- package/http-client/utils/index.d.ts +4 -0
- package/http-client/utils/index.js +20 -0
- package/http-client/utils/retry-recorder.util.d.ts +30 -0
- package/http-client/utils/retry-recorder.util.js +143 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
|
@@ -33,22 +33,23 @@ typeorm_1.SelectQueryBuilder.prototype.toDtoPage = function (pageOptionsDto, dto
|
|
|
33
33
|
const page = pageOptionsDto.page || 1;
|
|
34
34
|
const pageSize = pageOptionsDto.pageSize || 10;
|
|
35
35
|
const skip = (page - 1) * pageSize;
|
|
36
|
-
const
|
|
36
|
+
const total = yield this.getCount();
|
|
37
37
|
const entities = yield this.skip(skip).take(pageSize).getMany();
|
|
38
|
-
|
|
38
|
+
const count = entities.length;
|
|
39
|
+
if (count) {
|
|
39
40
|
console.log('Raw entity sample:', JSON.stringify(entities[0], null, 2));
|
|
40
41
|
}
|
|
41
42
|
const data = yield entities.toDto(dtoClass, context);
|
|
42
43
|
if (data.length > 0) {
|
|
43
44
|
console.log('Converted DTO sample:', JSON.stringify(data[0], null, 2));
|
|
44
45
|
}
|
|
45
|
-
const
|
|
46
|
-
const pageCount = Math.ceil(itemCount / pageSize);
|
|
46
|
+
const pageCount = Math.ceil(total / pageSize);
|
|
47
47
|
const hasPreviousPage = page > 1;
|
|
48
48
|
const hasNextPage = page < pageCount;
|
|
49
49
|
return {
|
|
50
50
|
data,
|
|
51
|
-
|
|
51
|
+
count,
|
|
52
|
+
total,
|
|
52
53
|
page,
|
|
53
54
|
pageCount,
|
|
54
55
|
hasPreviousPage,
|
package/common/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function generateHash(password: string): string;
|
|
2
2
|
export declare function validateHash(password: string | undefined, hash: string | undefined): Promise<boolean>;
|
|
3
3
|
export declare function getVariableName<TResult>(getVar: () => TResult): string;
|
|
4
|
+
export declare function generateRequestId(): string;
|
package/common/utils.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateHash = generateHash;
|
|
4
4
|
exports.validateHash = validateHash;
|
|
5
5
|
exports.getVariableName = getVariableName;
|
|
6
|
+
exports.generateRequestId = generateRequestId;
|
|
6
7
|
const bcrypt_1 = require("bcrypt");
|
|
7
8
|
function generateHash(password) {
|
|
8
9
|
return bcrypt_1.default.hashSync(password, 10);
|
|
@@ -22,3 +23,8 @@ function getVariableName(getVar) {
|
|
|
22
23
|
const memberParts = fullMemberName.split('.');
|
|
23
24
|
return memberParts[memberParts.length - 1];
|
|
24
25
|
}
|
|
26
|
+
function generateRequestId() {
|
|
27
|
+
return Math.random().toString(36).substring(2, 15) +
|
|
28
|
+
Math.random().toString(36).substring(2, 15) +
|
|
29
|
+
Date.now().toString(36);
|
|
30
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HttpClientConfig } from '../interfaces/http-client-config.interface';
|
|
2
|
+
export declare const DEFAULT_HTTP_CLIENT_CONFIG: Partial<HttpClientConfig>;
|
|
3
|
+
export declare const DEVELOPMENT_HTTP_CLIENT_CONFIG: Partial<HttpClientConfig>;
|
|
4
|
+
export declare const PRODUCTION_HTTP_CLIENT_CONFIG: Partial<HttpClientConfig>;
|
|
5
|
+
export declare const TEST_HTTP_CLIENT_CONFIG: Partial<HttpClientConfig>;
|
|
6
|
+
export declare function getHttpClientConfig(env?: string): Partial<HttpClientConfig>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TEST_HTTP_CLIENT_CONFIG = exports.PRODUCTION_HTTP_CLIENT_CONFIG = exports.DEVELOPMENT_HTTP_CLIENT_CONFIG = exports.DEFAULT_HTTP_CLIENT_CONFIG = void 0;
|
|
4
|
+
exports.getHttpClientConfig = getHttpClientConfig;
|
|
5
|
+
const cache_options_interface_1 = require("../../cache/interfaces/cache-options.interface");
|
|
6
|
+
exports.DEFAULT_HTTP_CLIENT_CONFIG = {
|
|
7
|
+
timeout: 30000,
|
|
8
|
+
retry: {
|
|
9
|
+
enabled: true,
|
|
10
|
+
retries: 3,
|
|
11
|
+
retryDelay: (retryCount) => Math.pow(2, retryCount) * 1000,
|
|
12
|
+
retryCondition: (error) => {
|
|
13
|
+
if (!error.response)
|
|
14
|
+
return true;
|
|
15
|
+
const status = error.response.status;
|
|
16
|
+
return status >= 500 || status === 429;
|
|
17
|
+
},
|
|
18
|
+
shouldResetTimeout: true,
|
|
19
|
+
},
|
|
20
|
+
circuitBreaker: {
|
|
21
|
+
enabled: true,
|
|
22
|
+
failureThreshold: 5,
|
|
23
|
+
recoveryTimeoutMs: 60000,
|
|
24
|
+
monitoringPeriodMs: 10000,
|
|
25
|
+
minimumThroughputThreshold: 10,
|
|
26
|
+
countHalfOpenCalls: false,
|
|
27
|
+
},
|
|
28
|
+
cache: {
|
|
29
|
+
enabled: true,
|
|
30
|
+
defaultTtl: 300000,
|
|
31
|
+
cacheableMethods: ['GET', 'HEAD'],
|
|
32
|
+
cacheableStatusCodes: [200, 201, 304],
|
|
33
|
+
options: {
|
|
34
|
+
layers: [cache_options_interface_1.CacheLayer.CLS, cache_options_interface_1.CacheLayer.MEMORY, cache_options_interface_1.CacheLayer.REDIS],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
logging: {
|
|
38
|
+
enabled: true,
|
|
39
|
+
logRequests: true,
|
|
40
|
+
logResponses: true,
|
|
41
|
+
logErrors: true,
|
|
42
|
+
logHeaders: false,
|
|
43
|
+
logBody: true,
|
|
44
|
+
maxBodyLength: 1000,
|
|
45
|
+
sanitizeHeaders: ['authorization', 'apikey', 'password', 'token', 'cookie'],
|
|
46
|
+
logLevel: 'info',
|
|
47
|
+
databaseLogging: {
|
|
48
|
+
enabled: false,
|
|
49
|
+
dataSource: 'default',
|
|
50
|
+
tableName: 'http_logs',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
logCleanup: {
|
|
54
|
+
enabled: false,
|
|
55
|
+
retentionDays: 30,
|
|
56
|
+
maxRecords: 100000,
|
|
57
|
+
batchSize: 1000,
|
|
58
|
+
schedule: '0 2 * * *',
|
|
59
|
+
strategy: 'retention',
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
exports.DEVELOPMENT_HTTP_CLIENT_CONFIG = Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG), { logging: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.logging), { enabled: true, logHeaders: true, logBody: true, logLevel: 'debug', databaseLogging: {
|
|
63
|
+
enabled: true,
|
|
64
|
+
dataSource: 'default',
|
|
65
|
+
tableName: 'http_logs',
|
|
66
|
+
} }), logCleanup: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.logCleanup), { enabled: false }) });
|
|
67
|
+
exports.PRODUCTION_HTTP_CLIENT_CONFIG = Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG), { timeout: 60000, retry: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.retry), { retries: 5 }), circuitBreaker: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.circuitBreaker), { failureThreshold: 3, recoveryTimeoutMs: 120000 }), logging: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.logging), { enabled: true, logHeaders: false, logBody: false, logLevel: 'warn', databaseLogging: {
|
|
68
|
+
enabled: true,
|
|
69
|
+
dataSource: 'default',
|
|
70
|
+
tableName: 'http_logs',
|
|
71
|
+
} }), logCleanup: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.logCleanup), { enabled: true, retentionDays: 7, maxRecords: 50000, schedule: '0 3 * * *' }) });
|
|
72
|
+
exports.TEST_HTTP_CLIENT_CONFIG = Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG), { timeout: 10000, retry: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.retry), { retries: 1 }), circuitBreaker: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.circuitBreaker), { failureThreshold: 10, recoveryTimeoutMs: 5000 }), logging: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.logging), { enabled: false }), logCleanup: Object.assign(Object.assign({}, exports.DEFAULT_HTTP_CLIENT_CONFIG.logCleanup), { enabled: false }) });
|
|
73
|
+
function getHttpClientConfig(env) {
|
|
74
|
+
switch (env === null || env === void 0 ? void 0 : env.toLowerCase()) {
|
|
75
|
+
case 'development':
|
|
76
|
+
case 'dev':
|
|
77
|
+
return exports.DEVELOPMENT_HTTP_CLIENT_CONFIG;
|
|
78
|
+
case 'production':
|
|
79
|
+
case 'prod':
|
|
80
|
+
return exports.PRODUCTION_HTTP_CLIENT_CONFIG;
|
|
81
|
+
case 'test':
|
|
82
|
+
case 'testing':
|
|
83
|
+
return exports.TEST_HTTP_CLIENT_CONFIG;
|
|
84
|
+
default:
|
|
85
|
+
return exports.DEFAULT_HTTP_CLIENT_CONFIG;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './http-client.config';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./http-client.config"), exports);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { CircuitBreakerConfig, HttpCacheConfig, HttpClientConfig, RetryConfig } from '../interfaces/http-client-config.interface';
|
|
3
|
+
export declare const HTTP_CLIENT_OPTIONS_KEY = "http_client_options";
|
|
4
|
+
export declare const RETRY_OPTIONS_KEY = "http_retry_options";
|
|
5
|
+
export declare const CIRCUIT_BREAKER_OPTIONS_KEY = "http_circuit_breaker_options";
|
|
6
|
+
export declare const CACHE_OPTIONS_KEY = "http_cache_options";
|
|
7
|
+
export declare const LOGGING_OPTIONS_KEY = "http_logging_options";
|
|
8
|
+
export declare const TIMEOUT_OPTIONS_KEY = "http_timeout_options";
|
|
9
|
+
export declare const PROXY_OPTIONS_KEY = "http_proxy_options";
|
|
10
|
+
export declare const CALL_INFO_KEY = "http_call_info";
|
|
11
|
+
export declare const HttpClient: (options?: HttpClientConfig) => (target: any) => void;
|
|
12
|
+
export declare const HttpRetry: (options?: {
|
|
13
|
+
retries?: number;
|
|
14
|
+
retryDelay?: (retryCount: number) => number;
|
|
15
|
+
retryCondition?: (error: any) => boolean;
|
|
16
|
+
shouldResetTimeout?: boolean;
|
|
17
|
+
onRetry?: (retryCount: number, error: any, requestConfig: any) => void;
|
|
18
|
+
}) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
19
|
+
export declare const HttpCircuitBreaker: (options?: {
|
|
20
|
+
failureThreshold?: number;
|
|
21
|
+
recoveryTimeoutMs?: number;
|
|
22
|
+
monitoringPeriodMs?: number;
|
|
23
|
+
minimumThroughputThreshold?: number;
|
|
24
|
+
}) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
25
|
+
export declare const HttpCacheable: (options?: {
|
|
26
|
+
ttl?: number;
|
|
27
|
+
key?: string | ((...args: any[]) => string);
|
|
28
|
+
layers?: Array<"cls" | "memory" | "redis">;
|
|
29
|
+
condition?: (...args: any[]) => boolean | Promise<boolean>;
|
|
30
|
+
unless?: string | ((result: any, args: any[]) => boolean);
|
|
31
|
+
namespace?: string;
|
|
32
|
+
}) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
33
|
+
export declare const HttpLogRequest: (options?: {
|
|
34
|
+
logHeaders?: boolean;
|
|
35
|
+
logBody?: boolean;
|
|
36
|
+
sanitizeHeaders?: string[];
|
|
37
|
+
databaseLog?: boolean;
|
|
38
|
+
logLevel?: "debug" | "info" | "warn" | "error";
|
|
39
|
+
serviceClass?: string;
|
|
40
|
+
methodName?: string;
|
|
41
|
+
operationName?: string;
|
|
42
|
+
}) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
43
|
+
export declare const HttpTimeout: (timeoutMs: number) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
44
|
+
export declare const HttpUseProxy: (options: {
|
|
45
|
+
host: string;
|
|
46
|
+
port: number;
|
|
47
|
+
protocol?: "http" | "https";
|
|
48
|
+
auth?: {
|
|
49
|
+
username: string;
|
|
50
|
+
password: string;
|
|
51
|
+
};
|
|
52
|
+
}) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
53
|
+
export declare class HttpDecoratorUtils {
|
|
54
|
+
static getRetryOptions(target: any, propertyKey: string): RetryConfig | undefined;
|
|
55
|
+
static getCircuitBreakerOptions(target: any, propertyKey: string): CircuitBreakerConfig | undefined;
|
|
56
|
+
static getCacheOptions(target: any, propertyKey: string): HttpCacheConfig | undefined;
|
|
57
|
+
static getLoggingOptions(target: any, propertyKey: string): any;
|
|
58
|
+
static getTimeoutOptions(target: any, propertyKey: string): number | undefined;
|
|
59
|
+
static getProxyOptions(target: any, propertyKey: string): any;
|
|
60
|
+
static getHttpClientOptions(target: any): HttpClientConfig;
|
|
61
|
+
static getCallInfoOptions(target: any, propertyKey: string): any;
|
|
62
|
+
static getAllDecoratorConfigs(target: any, propertyKey: string): {
|
|
63
|
+
retry?: RetryConfig;
|
|
64
|
+
circuitBreaker?: CircuitBreakerConfig;
|
|
65
|
+
cache?: HttpCacheConfig;
|
|
66
|
+
logging?: any;
|
|
67
|
+
timeout?: number;
|
|
68
|
+
proxy?: any;
|
|
69
|
+
httpClient?: HttpClientConfig;
|
|
70
|
+
callInfo?: any;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpDecoratorUtils = exports.HttpUseProxy = exports.HttpTimeout = exports.HttpLogRequest = exports.HttpCacheable = exports.HttpCircuitBreaker = exports.HttpRetry = exports.HttpClient = exports.CALL_INFO_KEY = exports.PROXY_OPTIONS_KEY = exports.TIMEOUT_OPTIONS_KEY = exports.LOGGING_OPTIONS_KEY = exports.CACHE_OPTIONS_KEY = exports.CIRCUIT_BREAKER_OPTIONS_KEY = exports.RETRY_OPTIONS_KEY = exports.HTTP_CLIENT_OPTIONS_KEY = void 0;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const cache_options_interface_1 = require("../../cache/interfaces/cache-options.interface");
|
|
7
|
+
const call_stack_extractor_util_1 = require("../utils/call-stack-extractor.util");
|
|
8
|
+
exports.HTTP_CLIENT_OPTIONS_KEY = 'http_client_options';
|
|
9
|
+
exports.RETRY_OPTIONS_KEY = 'http_retry_options';
|
|
10
|
+
exports.CIRCUIT_BREAKER_OPTIONS_KEY = 'http_circuit_breaker_options';
|
|
11
|
+
exports.CACHE_OPTIONS_KEY = 'http_cache_options';
|
|
12
|
+
exports.LOGGING_OPTIONS_KEY = 'http_logging_options';
|
|
13
|
+
exports.TIMEOUT_OPTIONS_KEY = 'http_timeout_options';
|
|
14
|
+
exports.PROXY_OPTIONS_KEY = 'http_proxy_options';
|
|
15
|
+
exports.CALL_INFO_KEY = 'http_call_info';
|
|
16
|
+
const HttpClient = (options = {}) => {
|
|
17
|
+
return (target) => {
|
|
18
|
+
(0, common_1.SetMetadata)(exports.HTTP_CLIENT_OPTIONS_KEY, options)(target);
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
exports.HttpClient = HttpClient;
|
|
22
|
+
const HttpRetry = (options = {}) => {
|
|
23
|
+
return (target, propertyKey, descriptor) => {
|
|
24
|
+
const retryOptions = {
|
|
25
|
+
enabled: true,
|
|
26
|
+
retries: options.retries || 3,
|
|
27
|
+
retryDelay: options.retryDelay || ((retryCount) => Math.pow(2, retryCount) * 1000),
|
|
28
|
+
retryCondition: options.retryCondition ||
|
|
29
|
+
((error) => {
|
|
30
|
+
if (!error.response)
|
|
31
|
+
return true;
|
|
32
|
+
const status = error.response.status;
|
|
33
|
+
return status >= 500 || status === 429;
|
|
34
|
+
}),
|
|
35
|
+
shouldResetTimeout: options.shouldResetTimeout !== false,
|
|
36
|
+
onRetry: options.onRetry,
|
|
37
|
+
};
|
|
38
|
+
(0, common_1.SetMetadata)(`${exports.RETRY_OPTIONS_KEY}_${propertyKey}`, retryOptions)(descriptor.value);
|
|
39
|
+
return descriptor;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
exports.HttpRetry = HttpRetry;
|
|
43
|
+
const HttpCircuitBreaker = (options = {}) => {
|
|
44
|
+
return (target, propertyKey, descriptor) => {
|
|
45
|
+
const circuitBreakerOptions = {
|
|
46
|
+
enabled: true,
|
|
47
|
+
failureThreshold: options.failureThreshold || 5,
|
|
48
|
+
recoveryTimeoutMs: options.recoveryTimeoutMs || 60000,
|
|
49
|
+
monitoringPeriodMs: options.monitoringPeriodMs || 10000,
|
|
50
|
+
minimumThroughputThreshold: options.minimumThroughputThreshold || 10,
|
|
51
|
+
countHalfOpenCalls: true,
|
|
52
|
+
};
|
|
53
|
+
(0, common_1.SetMetadata)(`${exports.CIRCUIT_BREAKER_OPTIONS_KEY}_${propertyKey}`, circuitBreakerOptions)(descriptor.value);
|
|
54
|
+
return descriptor;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
exports.HttpCircuitBreaker = HttpCircuitBreaker;
|
|
58
|
+
const HttpCacheable = (options = {}) => {
|
|
59
|
+
return (target, propertyKey, descriptor) => {
|
|
60
|
+
var _a;
|
|
61
|
+
const cacheOptions = {
|
|
62
|
+
enabled: true,
|
|
63
|
+
defaultTtl: options.ttl || 300000,
|
|
64
|
+
keyGenerator: typeof options.key === 'function'
|
|
65
|
+
? (config) => options.key(config.url, config.method, config.data, config.params)
|
|
66
|
+
: options.key
|
|
67
|
+
? () => options.key
|
|
68
|
+
: undefined,
|
|
69
|
+
options: {
|
|
70
|
+
layers: (_a = options.layers) === null || _a === void 0 ? void 0 : _a.map((layer) => {
|
|
71
|
+
switch (layer) {
|
|
72
|
+
case 'cls':
|
|
73
|
+
return cache_options_interface_1.CacheLayer.CLS;
|
|
74
|
+
case 'memory':
|
|
75
|
+
return cache_options_interface_1.CacheLayer.MEMORY;
|
|
76
|
+
case 'redis':
|
|
77
|
+
return cache_options_interface_1.CacheLayer.REDIS;
|
|
78
|
+
default:
|
|
79
|
+
return cache_options_interface_1.CacheLayer.MEMORY;
|
|
80
|
+
}
|
|
81
|
+
}),
|
|
82
|
+
condition: options.condition,
|
|
83
|
+
prefix: options.namespace,
|
|
84
|
+
},
|
|
85
|
+
cacheableMethods: ['get'],
|
|
86
|
+
cacheableStatusCodes: [200, 201, 202, 204, 301, 302, 304],
|
|
87
|
+
};
|
|
88
|
+
if (options.unless) {
|
|
89
|
+
const originalMethod = descriptor.value;
|
|
90
|
+
descriptor.value = function (...args) {
|
|
91
|
+
const result = originalMethod.apply(this, args);
|
|
92
|
+
if (typeof options.unless === 'string') {
|
|
93
|
+
if (evalInContext(options.unless, { result, args })) {
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (typeof options.unless === 'function') {
|
|
98
|
+
if (options.unless(result, args)) {
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
(0, common_1.SetMetadata)(`${exports.CACHE_OPTIONS_KEY}_${propertyKey}`, cacheOptions)(originalMethod);
|
|
103
|
+
return result;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
(0, common_1.SetMetadata)(`${exports.CACHE_OPTIONS_KEY}_${propertyKey}`, cacheOptions)(descriptor.value);
|
|
108
|
+
}
|
|
109
|
+
return descriptor;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
exports.HttpCacheable = HttpCacheable;
|
|
113
|
+
const HttpLogRequest = (options = {}) => {
|
|
114
|
+
return (target, propertyKey, descriptor) => {
|
|
115
|
+
var _a, _b, _c;
|
|
116
|
+
const loggingOptions = {
|
|
117
|
+
logHeaders: (_a = options.logHeaders) !== null && _a !== void 0 ? _a : true,
|
|
118
|
+
logBody: (_b = options.logBody) !== null && _b !== void 0 ? _b : true,
|
|
119
|
+
sanitizeHeaders: options.sanitizeHeaders || [
|
|
120
|
+
'authorization',
|
|
121
|
+
'apikey',
|
|
122
|
+
'password',
|
|
123
|
+
'token',
|
|
124
|
+
'x-api-key',
|
|
125
|
+
'cookie',
|
|
126
|
+
'set-cookie',
|
|
127
|
+
],
|
|
128
|
+
databaseLog: (_c = options.databaseLog) !== null && _c !== void 0 ? _c : false,
|
|
129
|
+
logLevel: options.logLevel || 'info',
|
|
130
|
+
};
|
|
131
|
+
const decoratorInfo = call_stack_extractor_util_1.CallStackExtractor.extractFromDecorator(target, propertyKey);
|
|
132
|
+
const callInfo = {
|
|
133
|
+
serviceClass: options.serviceClass || decoratorInfo.serviceClass,
|
|
134
|
+
methodName: options.methodName || decoratorInfo.methodName,
|
|
135
|
+
operationName: options.operationName || decoratorInfo.operationName,
|
|
136
|
+
};
|
|
137
|
+
(0, common_1.SetMetadata)(`${exports.LOGGING_OPTIONS_KEY}_${propertyKey}`, loggingOptions)(descriptor.value);
|
|
138
|
+
(0, common_1.SetMetadata)(`${exports.CALL_INFO_KEY}_${propertyKey}`, callInfo)(descriptor.value);
|
|
139
|
+
return descriptor;
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
exports.HttpLogRequest = HttpLogRequest;
|
|
143
|
+
const HttpTimeout = (timeoutMs) => {
|
|
144
|
+
return (target, propertyKey, descriptor) => {
|
|
145
|
+
(0, common_1.SetMetadata)(`${exports.TIMEOUT_OPTIONS_KEY}_${propertyKey}`, timeoutMs)(descriptor.value);
|
|
146
|
+
return descriptor;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
exports.HttpTimeout = HttpTimeout;
|
|
150
|
+
const HttpUseProxy = (options) => {
|
|
151
|
+
return (target, propertyKey, descriptor) => {
|
|
152
|
+
(0, common_1.SetMetadata)(`${exports.PROXY_OPTIONS_KEY}_${propertyKey}`, options)(descriptor.value);
|
|
153
|
+
return descriptor;
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
exports.HttpUseProxy = HttpUseProxy;
|
|
157
|
+
class HttpDecoratorUtils {
|
|
158
|
+
static getRetryOptions(target, propertyKey) {
|
|
159
|
+
return Reflect.getMetadata(`${exports.RETRY_OPTIONS_KEY}_${propertyKey}`, target[propertyKey]);
|
|
160
|
+
}
|
|
161
|
+
static getCircuitBreakerOptions(target, propertyKey) {
|
|
162
|
+
return Reflect.getMetadata(`${exports.CIRCUIT_BREAKER_OPTIONS_KEY}_${propertyKey}`, target[propertyKey]);
|
|
163
|
+
}
|
|
164
|
+
static getCacheOptions(target, propertyKey) {
|
|
165
|
+
return Reflect.getMetadata(`${exports.CACHE_OPTIONS_KEY}_${propertyKey}`, target[propertyKey]);
|
|
166
|
+
}
|
|
167
|
+
static getLoggingOptions(target, propertyKey) {
|
|
168
|
+
return Reflect.getMetadata(`${exports.LOGGING_OPTIONS_KEY}_${propertyKey}`, target[propertyKey]);
|
|
169
|
+
}
|
|
170
|
+
static getTimeoutOptions(target, propertyKey) {
|
|
171
|
+
return Reflect.getMetadata(`${exports.TIMEOUT_OPTIONS_KEY}_${propertyKey}`, target[propertyKey]);
|
|
172
|
+
}
|
|
173
|
+
static getProxyOptions(target, propertyKey) {
|
|
174
|
+
return Reflect.getMetadata(`${exports.PROXY_OPTIONS_KEY}_${propertyKey}`, target[propertyKey]);
|
|
175
|
+
}
|
|
176
|
+
static getHttpClientOptions(target) {
|
|
177
|
+
return Reflect.getMetadata(exports.HTTP_CLIENT_OPTIONS_KEY, target) || {};
|
|
178
|
+
}
|
|
179
|
+
static getCallInfoOptions(target, propertyKey) {
|
|
180
|
+
return Reflect.getMetadata(`${exports.CALL_INFO_KEY}_${propertyKey}`, target[propertyKey]);
|
|
181
|
+
}
|
|
182
|
+
static getAllDecoratorConfigs(target, propertyKey) {
|
|
183
|
+
return {
|
|
184
|
+
retry: this.getRetryOptions(target, propertyKey),
|
|
185
|
+
circuitBreaker: this.getCircuitBreakerOptions(target, propertyKey),
|
|
186
|
+
cache: this.getCacheOptions(target, propertyKey),
|
|
187
|
+
logging: this.getLoggingOptions(target, propertyKey),
|
|
188
|
+
timeout: this.getTimeoutOptions(target, propertyKey),
|
|
189
|
+
proxy: this.getProxyOptions(target, propertyKey),
|
|
190
|
+
httpClient: this.getHttpClientOptions(target),
|
|
191
|
+
callInfo: this.getCallInfoOptions(target, propertyKey),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
exports.HttpDecoratorUtils = HttpDecoratorUtils;
|
|
196
|
+
function evalInContext(expression, context) {
|
|
197
|
+
try {
|
|
198
|
+
const func = new Function(...Object.keys(context), `return ${expression}`);
|
|
199
|
+
return func(...Object.values(context));
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './http-client.decorators';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./http-client.decorators"), exports);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { AbstractUuidPrimaryEntity } from '../../common';
|
|
2
|
+
export declare class HttpLogEntity extends AbstractUuidPrimaryEntity {
|
|
3
|
+
requestId?: string;
|
|
4
|
+
userId?: string;
|
|
5
|
+
method: string;
|
|
6
|
+
url: string;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
body?: string;
|
|
9
|
+
params?: Record<string, any>;
|
|
10
|
+
statusCode?: number;
|
|
11
|
+
responseTime: number;
|
|
12
|
+
attemptCount: number;
|
|
13
|
+
success: boolean;
|
|
14
|
+
errorMessage?: string;
|
|
15
|
+
errorStack?: string;
|
|
16
|
+
errorCode?: string;
|
|
17
|
+
responseHeaders?: Record<string, string>;
|
|
18
|
+
responseBody?: string;
|
|
19
|
+
responseSize?: number;
|
|
20
|
+
requestSize?: number;
|
|
21
|
+
serviceName?: string;
|
|
22
|
+
operationName?: string;
|
|
23
|
+
clientIp?: string;
|
|
24
|
+
source?: string;
|
|
25
|
+
tags?: string[];
|
|
26
|
+
metadata?: Record<string, any>;
|
|
27
|
+
retryRecords?: RetryRecord[];
|
|
28
|
+
cacheHit?: boolean;
|
|
29
|
+
circuitBreakerState?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface RetryRecord {
|
|
32
|
+
attempt: number;
|
|
33
|
+
timestamp: Date;
|
|
34
|
+
reason: string;
|
|
35
|
+
delay: number;
|
|
36
|
+
error?: {
|
|
37
|
+
message: string;
|
|
38
|
+
code?: string;
|
|
39
|
+
statusCode?: number;
|
|
40
|
+
};
|
|
41
|
+
requestConfig?: {
|
|
42
|
+
method: string;
|
|
43
|
+
url: string;
|
|
44
|
+
headers: Record<string, string>;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface HttpLogQueryOptions {
|
|
48
|
+
requestId?: string;
|
|
49
|
+
userId?: string;
|
|
50
|
+
method?: string | string[];
|
|
51
|
+
url?: string;
|
|
52
|
+
statusCode?: number | number[];
|
|
53
|
+
success?: boolean;
|
|
54
|
+
serviceName?: string;
|
|
55
|
+
operationName?: string;
|
|
56
|
+
clientIp?: string;
|
|
57
|
+
source?: string;
|
|
58
|
+
tags?: string[];
|
|
59
|
+
errorCode?: string;
|
|
60
|
+
minResponseTime?: number;
|
|
61
|
+
maxResponseTime?: number;
|
|
62
|
+
startDate?: Date;
|
|
63
|
+
endDate?: Date;
|
|
64
|
+
keyword?: string;
|
|
65
|
+
page?: number;
|
|
66
|
+
limit?: number;
|
|
67
|
+
sortBy?: 'createdAt' | 'responseTime' | 'statusCode' | 'url';
|
|
68
|
+
sortOrder?: 'ASC' | 'DESC';
|
|
69
|
+
includeDetails?: boolean;
|
|
70
|
+
}
|
|
71
|
+
export interface HttpLogStats {
|
|
72
|
+
totalRequests: number;
|
|
73
|
+
successfulRequests: number;
|
|
74
|
+
failedRequests: number;
|
|
75
|
+
successRate: number;
|
|
76
|
+
averageResponseTime: number;
|
|
77
|
+
minResponseTime: number;
|
|
78
|
+
maxResponseTime: number;
|
|
79
|
+
p50ResponseTime: number;
|
|
80
|
+
p95ResponseTime: number;
|
|
81
|
+
p99ResponseTime: number;
|
|
82
|
+
requestsByMethod: Record<string, number>;
|
|
83
|
+
requestsByStatus: Record<string, number>;
|
|
84
|
+
requestsByService: Record<string, number>;
|
|
85
|
+
requestsBySource: Record<string, number>;
|
|
86
|
+
errorsByCode: Record<string, number>;
|
|
87
|
+
retryStats: {
|
|
88
|
+
totalRetries: number;
|
|
89
|
+
averageRetries: number;
|
|
90
|
+
maxRetries: number;
|
|
91
|
+
retryRate: number;
|
|
92
|
+
};
|
|
93
|
+
cacheStats: {
|
|
94
|
+
cacheHits: number;
|
|
95
|
+
cacheMisses: number;
|
|
96
|
+
cacheHitRate: number;
|
|
97
|
+
};
|
|
98
|
+
}
|