@diia-inhouse/http 4.0.26 → 5.1.0

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 (40) hide show
  1. package/dist/index.d.ts +5 -0
  2. package/dist/index.js +4 -19
  3. package/dist/interfaces/deps.d.ts +7 -0
  4. package/dist/interfaces/httpClient.d.ts +77 -0
  5. package/dist/interfaces/index.d.ts +2 -0
  6. package/dist/services/errors/index.js +3 -8
  7. package/dist/services/errors/operationError.d.ts +8 -0
  8. package/dist/services/errors/operationError.js +11 -13
  9. package/dist/services/errors/requestError.d.ts +8 -0
  10. package/dist/services/errors/requestError.js +13 -15
  11. package/dist/services/httpClient.d.ts +25 -0
  12. package/dist/services/httpClient.js +207 -233
  13. package/dist/services/index.d.ts +2 -0
  14. package/dist/services/index.js +3 -21
  15. package/dist/services/utils.d.ts +6 -0
  16. package/dist/services/utils.js +12 -18
  17. package/package.json +41 -32
  18. package/dist/index.js.map +0 -1
  19. package/dist/interfaces/deps.js +0 -3
  20. package/dist/interfaces/deps.js.map +0 -1
  21. package/dist/interfaces/httpClient.js +0 -3
  22. package/dist/interfaces/httpClient.js.map +0 -1
  23. package/dist/interfaces/index.js +0 -19
  24. package/dist/interfaces/index.js.map +0 -1
  25. package/dist/services/errors/index.js.map +0 -1
  26. package/dist/services/errors/operationError.js.map +0 -1
  27. package/dist/services/errors/requestError.js.map +0 -1
  28. package/dist/services/httpClient.js.map +0 -1
  29. package/dist/services/index.js.map +0 -1
  30. package/dist/services/utils.js.map +0 -1
  31. package/dist/types/index.d.ts +0 -2
  32. package/dist/types/interfaces/deps.d.ts +0 -4
  33. package/dist/types/interfaces/httpClient.d.ts +0 -73
  34. package/dist/types/interfaces/index.d.ts +0 -2
  35. package/dist/types/services/errors/index.d.ts +0 -2
  36. package/dist/types/services/errors/operationError.d.ts +0 -4
  37. package/dist/types/services/errors/requestError.d.ts +0 -5
  38. package/dist/types/services/httpClient.d.ts +0 -21
  39. package/dist/types/services/index.d.ts +0 -2
  40. package/dist/types/services/utils.d.ts +0 -4
@@ -0,0 +1,5 @@
1
+ import { FailureResponse, FullRequestOptions, HttpClientResponse, ObserveRequestBaseParams, ObserveRequestFailedParams, ReadonlyQuery, RequestHelperResponse, RequestOptions, SuccessfulResponse } from "./interfaces/httpClient.js";
2
+ import { HttpClientService } from "./services/httpClient.js";
3
+ import { checkServerIdentity } from "./services/utils.js";
4
+ import { HttpDeps } from "./interfaces/deps.js";
5
+ export { FailureResponse, FullRequestOptions, HttpClientResponse, HttpClientService, HttpDeps, ObserveRequestBaseParams, ObserveRequestFailedParams, ReadonlyQuery, RequestHelperResponse, RequestOptions, SuccessfulResponse, checkServerIdentity };
package/dist/index.js CHANGED
@@ -1,19 +1,4 @@
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("./services"), exports);
18
- __exportStar(require("./interfaces"), exports);
19
- //# sourceMappingURL=index.js.map
1
+ import { checkServerIdentity } from "./services/utils.js";
2
+ import { HttpClientService } from "./services/httpClient.js";
3
+ import "./services/index.js";
4
+ export { HttpClientService, checkServerIdentity };
@@ -0,0 +1,7 @@
1
+ import { HttpClientService } from "../services/httpClient.js";
2
+ //#region src/interfaces/deps.d.ts
3
+ type HttpDeps<TMetricLabel extends string> = {
4
+ http?: HttpClientService<TMetricLabel>;
5
+ };
6
+ //#endregion
7
+ export { HttpDeps };
@@ -0,0 +1,77 @@
1
+ import { RequestError } from "../services/errors/requestError.js";
2
+ import { OperationError } from "../services/errors/operationError.js";
3
+ import { Span } from "@opentelemetry/api";
4
+ import { AxiosResponse, ResponseType } from "axios";
5
+ import { ErrorType } from "@diia-inhouse/errors";
6
+ import { HttpMethod, HttpStatusCode } from "@diia-inhouse/types";
7
+ import { Agent } from "node:http";
8
+ import { Agent as Agent$1 } from "node:https";
9
+
10
+ //#region src/interfaces/httpClient.d.ts
11
+ type ReadonlyQuery = Readonly<object>;
12
+ /**
13
+ * Enforces that T is a string literal or union of literals, not the broad `string` type.
14
+ * Resolves to `never` if T is exactly `string`, causing a compile error.
15
+ */
16
+ type LowCardinality<T extends string> = string extends T ? never : T;
17
+ interface RequestOptions<TMetricLabel extends string> {
18
+ baseUrl?: string;
19
+ timeout?: number;
20
+ retries?: number;
21
+ retryInterval?: number;
22
+ query?: ReadonlyQuery;
23
+ headers?: Record<string, string>;
24
+ body?: unknown;
25
+ errorType?: ErrorType;
26
+ responseType?: ResponseType;
27
+ httpsAgent?: Agent$1;
28
+ httpAgent?: Agent;
29
+ /**
30
+ * Label used to separate metrics on the same destination host.
31
+ *
32
+ * **Must have low cardinality** — use a finite set of known values, not dynamic strings
33
+ * like URLs, IDs, or user input. High-cardinality labels cause metric explosion and
34
+ * degrade monitoring system performance.
35
+ *
36
+ * Define as a string union type to enforce allowed values at compile time:
37
+ * @example
38
+ * type MyMetricLabel = 'getUserProfile' | 'createOrder' | 'validateDocument'
39
+ * const options: RequestOptions<MyMetricLabel> = { metricLabel: 'getUserProfile', ... }
40
+ */
41
+ metricLabel: LowCardinality<TMetricLabel>;
42
+ }
43
+ interface FullRequestOptions<TMetricLabel extends string> extends RequestOptions<TMetricLabel> {
44
+ path: string;
45
+ method: HttpMethod;
46
+ }
47
+ interface SuccessfulResponse<T> {
48
+ isOk: true;
49
+ statusCode: HttpStatusCode;
50
+ headers?: Record<string, string>;
51
+ body: T;
52
+ }
53
+ interface FailureResponse<TError> {
54
+ isOk: false;
55
+ statusCode: HttpStatusCode;
56
+ headers?: Record<string, string>;
57
+ body: TError | undefined;
58
+ }
59
+ type HttpClientResponse<TResponse, TError = unknown> = SuccessfulResponse<TResponse> | FailureResponse<TError>;
60
+ interface ObserveRequestBaseParams {
61
+ statusCode: number;
62
+ retryCount: number;
63
+ startTime: bigint;
64
+ span: Span;
65
+ baseUrl: string;
66
+ metricLabel: string;
67
+ }
68
+ interface ObserveRequestFailedParams extends ObserveRequestBaseParams {
69
+ errorType: ErrorType;
70
+ }
71
+ interface RequestHelperResponse<TResponse> {
72
+ response?: AxiosResponse<TResponse>;
73
+ error?: RequestError | OperationError;
74
+ retryCount: number;
75
+ }
76
+ //#endregion
77
+ export { FailureResponse, FullRequestOptions, HttpClientResponse, ObserveRequestBaseParams, ObserveRequestFailedParams, ReadonlyQuery, RequestHelperResponse, RequestOptions, SuccessfulResponse };
@@ -0,0 +1,2 @@
1
+ import { FailureResponse, FullRequestOptions, HttpClientResponse, ObserveRequestBaseParams, ObserveRequestFailedParams, ReadonlyQuery, RequestHelperResponse, RequestOptions, SuccessfulResponse } from "./httpClient.js";
2
+ import { HttpDeps } from "./deps.js";
@@ -1,8 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RequestError = exports.OperationError = void 0;
4
- var operationError_1 = require("./operationError");
5
- Object.defineProperty(exports, "OperationError", { enumerable: true, get: function () { return operationError_1.OperationError; } });
6
- var requestError_1 = require("./requestError");
7
- Object.defineProperty(exports, "RequestError", { enumerable: true, get: function () { return requestError_1.RequestError; } });
8
- //# sourceMappingURL=index.js.map
1
+ import "./requestError.js";
2
+ import "./operationError.js";
3
+ export {};
@@ -0,0 +1,8 @@
1
+ import { RequestError } from "./requestError.js";
2
+
3
+ //#region src/services/errors/operationError.d.ts
4
+ declare class OperationError extends RequestError {
5
+ constructor(message: string, originalError: Error);
6
+ }
7
+ //#endregion
8
+ export { OperationError };
@@ -1,13 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OperationError = void 0;
4
- const types_1 = require("@diia-inhouse/types");
5
- const requestError_1 = require("./requestError");
6
- class OperationError extends requestError_1.RequestError {
7
- constructor(message, originalError) {
8
- super(message, types_1.HttpStatusCode.INTERNAL_SERVER_ERROR, originalError);
9
- this.name = 'OperationError';
10
- }
11
- }
12
- exports.OperationError = OperationError;
13
- //# sourceMappingURL=operationError.js.map
1
+ import { RequestError } from "./requestError.js";
2
+ import { HttpStatusCode } from "@diia-inhouse/types";
3
+ //#region src/services/errors/operationError.ts
4
+ var OperationError = class extends RequestError {
5
+ constructor(message, originalError) {
6
+ super(message, HttpStatusCode.INTERNAL_SERVER_ERROR, originalError);
7
+ this.name = "OperationError";
8
+ }
9
+ };
10
+ //#endregion
11
+ export { OperationError };
@@ -0,0 +1,8 @@
1
+ //#region src/services/errors/requestError.d.ts
2
+ declare class RequestError extends Error {
3
+ readonly statusCode: number;
4
+ readonly originalError: Error;
5
+ constructor(message: string, statusCode: number, originalError: Error);
6
+ }
7
+ //#endregion
8
+ export { RequestError };
@@ -1,15 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RequestError = void 0;
4
- class RequestError extends Error {
5
- statusCode;
6
- originalError;
7
- constructor(message, statusCode, originalError) {
8
- super(message);
9
- this.name = 'RequestError';
10
- this.statusCode = statusCode;
11
- this.originalError = originalError;
12
- }
13
- }
14
- exports.RequestError = RequestError;
15
- //# sourceMappingURL=requestError.js.map
1
+ //#region src/services/errors/requestError.ts
2
+ var RequestError = class extends Error {
3
+ statusCode;
4
+ originalError;
5
+ constructor(message, statusCode, originalError) {
6
+ super(message);
7
+ this.name = "RequestError";
8
+ this.statusCode = statusCode;
9
+ this.originalError = originalError;
10
+ }
11
+ };
12
+ //#endregion
13
+ export { RequestError };
@@ -0,0 +1,25 @@
1
+ import { HttpClientResponse, RequestOptions } from "../interfaces/httpClient.js";
2
+ import { MetricsService } from "@diia-inhouse/diia-metrics";
3
+ import { Logger } from "@diia-inhouse/types";
4
+
5
+ //#region src/services/httpClient.d.ts
6
+ declare class HttpClientService<TMetricLabel extends string> {
7
+ private logger;
8
+ private metrics;
9
+ private readonly systemServiceName;
10
+ private readonly timeout;
11
+ private readonly baseUrl;
12
+ constructor(logger: Logger, metrics: MetricsService, systemServiceName: string, timeout?: number, baseUrl?: string);
13
+ get<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
14
+ post<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
15
+ put<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
16
+ delete<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
17
+ patch<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
18
+ private request;
19
+ private requestHelper;
20
+ private observeSuccessRequest;
21
+ private observeFailedRequest;
22
+ private getLabels;
23
+ }
24
+ //#endregion
25
+ export { HttpClientService };
@@ -1,233 +1,207 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.HttpClientService = void 0;
37
- const api_1 = require("@opentelemetry/api");
38
- const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
39
- const axios_1 = __importStar(require("axios"));
40
- const diia_metrics_1 = require("@diia-inhouse/diia-metrics");
41
- const errors_1 = require("@diia-inhouse/errors");
42
- const types_1 = require("@diia-inhouse/types");
43
- const errors_2 = require("./errors");
44
- const utils_1 = require("./utils");
45
- class HttpClientService {
46
- logger;
47
- metrics;
48
- systemServiceName;
49
- timeout;
50
- baseUrl;
51
- constructor(logger, metrics, systemServiceName, timeout = types_1.DurationMs.Second * 30, baseUrl = '') {
52
- this.logger = logger;
53
- this.metrics = metrics;
54
- this.systemServiceName = systemServiceName;
55
- this.timeout = timeout;
56
- this.baseUrl = baseUrl;
57
- }
58
- async get(path, opts) {
59
- return await this.request({
60
- path,
61
- method: types_1.HttpMethod.GET,
62
- ...opts,
63
- });
64
- }
65
- async post(path, opts) {
66
- return await this.request({
67
- path,
68
- method: types_1.HttpMethod.POST,
69
- ...opts,
70
- });
71
- }
72
- async put(path, opts) {
73
- return await this.request({
74
- path,
75
- method: types_1.HttpMethod.PUT,
76
- ...opts,
77
- });
78
- }
79
- async delete(path, opts) {
80
- return await this.request({
81
- path,
82
- method: types_1.HttpMethod.DELETE,
83
- ...opts,
84
- });
85
- }
86
- async patch(path, opts) {
87
- return await this.request({
88
- path,
89
- method: types_1.HttpMethod.PATCH,
90
- ...opts,
91
- });
92
- }
93
- async request(opts) {
94
- const activeContext = api_1.context.active();
95
- const tracer = api_1.trace.getTracer(this.systemServiceName);
96
- const baseUrl = opts.baseUrl || this.baseUrl;
97
- if (!baseUrl) {
98
- throw new Error('Base URL is not provided');
99
- }
100
- const span = tracer.startSpan(opts.method, {
101
- kind: api_1.SpanKind.CLIENT,
102
- attributes: {
103
- [semantic_conventions_1.SEMATTRS_MESSAGING_SYSTEM]: diia_metrics_1.RequestMechanism.Http,
104
- [semantic_conventions_1.SemanticAttributes.HTTP_METHOD]: opts.method,
105
- [semantic_conventions_1.SemanticAttributes.HTTP_URL]: `${baseUrl}${opts.path}`,
106
- [semantic_conventions_1.SemanticAttributes.HTTP_TARGET]: opts.path,
107
- 'messaging.caller': this.systemServiceName,
108
- },
109
- }, activeContext);
110
- const { response, error, retryCount } = await this.requestHelper({ ...opts, baseUrl }, span);
111
- span?.setAttribute('retryCount', retryCount);
112
- if (response) {
113
- const statusCode = response.status;
114
- this.logger.info('HTTP request succeeded', {
115
- statusCode,
116
- path: opts.path,
117
- method: opts.method,
118
- });
119
- span?.setStatus({ code: api_1.SpanStatusCode.OK });
120
- span?.setAttribute(semantic_conventions_1.SemanticAttributes.HTTP_STATUS_CODE, statusCode);
121
- span?.end();
122
- return {
123
- isOk: true,
124
- statusCode,
125
- headers: response.headers || {},
126
- body: response.data,
127
- };
128
- }
129
- if (error) {
130
- const { statusCode, originalError } = error;
131
- this.logger.error('HTTP request failed', {
132
- err: error,
133
- method: opts.method,
134
- path: opts.path,
135
- statusCode,
136
- });
137
- span?.setStatus({ code: api_1.SpanStatusCode.ERROR });
138
- span?.recordException({
139
- name: originalError.name || 'Unexpected error',
140
- message: originalError.message,
141
- code: statusCode,
142
- });
143
- span?.end();
144
- return {
145
- isOk: false,
146
- statusCode,
147
- body: originalError instanceof axios_1.AxiosError ? originalError.response?.data : undefined,
148
- headers: originalError instanceof axios_1.AxiosError ? originalError.response?.headers || {} : {},
149
- };
150
- }
151
- throw new Error('Unexpected error caused');
152
- }
153
- async requestHelper(opts, span, currentRequestRetries = 0) {
154
- const timeout = opts.timeout || this.timeout;
155
- const { method, path, baseUrl, query = {}, body, headers = {}, responseType = 'json', retries = 0, retryInterval = 0, httpsAgent, httpAgent, errorType: errorTypeOps, metricLabel, } = opts;
156
- const startTime = process.hrtime.bigint();
157
- span.addEvent('request', { message: `Started processing request. Retry count ${currentRequestRetries}` });
158
- try {
159
- const response = await axios_1.default.request({
160
- method,
161
- baseURL: baseUrl,
162
- url: path,
163
- params: query,
164
- data: body,
165
- headers,
166
- responseType,
167
- timeout,
168
- httpsAgent,
169
- httpAgent,
170
- });
171
- this.observeSuccessRequest({
172
- statusCode: response.status,
173
- retryCount: currentRequestRetries,
174
- startTime,
175
- span,
176
- baseUrl: baseUrl,
177
- metricLabel,
178
- });
179
- return { response, retryCount: currentRequestRetries };
180
- }
181
- catch (err) {
182
- const statusCode = err?.response?.status || types_1.HttpStatusCode.INTERNAL_SERVER_ERROR;
183
- const errorType = errors_1.ErrorType.External || errorTypeOps;
184
- this.observeFailedRequest({
185
- statusCode,
186
- retryCount: currentRequestRetries,
187
- startTime,
188
- span,
189
- errorType,
190
- baseUrl: baseUrl,
191
- metricLabel,
192
- });
193
- if (err instanceof axios_1.AxiosError) {
194
- if (currentRequestRetries < retries) {
195
- this.logger.info('Retrying HTTP request', {
196
- err,
197
- path,
198
- retries: currentRequestRetries + 1,
199
- });
200
- return await (0, utils_1.waitAndRun)(() => this.requestHelper(opts, span, currentRequestRetries + 1), retryInterval);
201
- }
202
- const requestError = new errors_2.RequestError(err.message, statusCode, err);
203
- return { error: requestError, retryCount: currentRequestRetries };
204
- }
205
- const operationError = new errors_2.OperationError('Internal package error', err);
206
- return { error: operationError, retryCount: currentRequestRetries };
207
- }
208
- }
209
- observeSuccessRequest(params) {
210
- const { statusCode, retryCount, startTime, span, baseUrl, metricLabel } = params;
211
- const labels = this.getLabels(statusCode, diia_metrics_1.RequestStatus.Successful, baseUrl, metricLabel);
212
- span.addEvent('request', { message: `Finished processing request. Retry count ${retryCount}` });
213
- this.metrics.totalTimerMetric.observeSeconds(labels, process.hrtime.bigint() - startTime);
214
- }
215
- observeFailedRequest(params) {
216
- const { statusCode, retryCount, startTime, span, errorType, baseUrl, metricLabel } = params;
217
- const labels = this.getLabels(statusCode, diia_metrics_1.RequestStatus.Failed, baseUrl, metricLabel, errorType);
218
- span.addEvent('request', { message: `Finished processing request. Retry count ${retryCount}` });
219
- this.metrics.totalTimerMetric.observeSeconds(labels, process.hrtime.bigint() - startTime);
220
- }
221
- getLabels(statusCode, status, baseUrl, metricLabel, errorType) {
222
- return {
223
- status,
224
- statusCode,
225
- source: this.systemServiceName,
226
- destination: `${baseUrl}|${metricLabel}`,
227
- mechanism: diia_metrics_1.RequestMechanism.Http,
228
- ...(errorType ? { errorType } : {}),
229
- };
230
- }
231
- }
232
- exports.HttpClientService = HttpClientService;
233
- //# sourceMappingURL=httpClient.js.map
1
+ import { RequestError } from "./errors/requestError.js";
2
+ import { OperationError } from "./errors/operationError.js";
3
+ import "./errors/index.js";
4
+ import { waitAndRun } from "./utils.js";
5
+ import { SpanKind, SpanStatusCode, context, trace } from "@opentelemetry/api";
6
+ import { SEMATTRS_MESSAGING_SYSTEM, SemanticAttributes } from "@opentelemetry/semantic-conventions";
7
+ import axios, { AxiosError } from "axios";
8
+ import { RequestMechanism, RequestStatus } from "@diia-inhouse/diia-metrics";
9
+ import { ErrorType } from "@diia-inhouse/errors";
10
+ import { DurationMs, HttpMethod, HttpStatusCode } from "@diia-inhouse/types";
11
+ //#region src/services/httpClient.ts
12
+ var HttpClientService = class {
13
+ logger;
14
+ metrics;
15
+ systemServiceName;
16
+ timeout;
17
+ baseUrl;
18
+ constructor(logger, metrics, systemServiceName, timeout = DurationMs.Second * 30, baseUrl = "") {
19
+ this.logger = logger;
20
+ this.metrics = metrics;
21
+ this.systemServiceName = systemServiceName;
22
+ this.timeout = timeout;
23
+ this.baseUrl = baseUrl;
24
+ }
25
+ async get(path, opts) {
26
+ return await this.request({
27
+ path,
28
+ method: HttpMethod.GET,
29
+ ...opts
30
+ });
31
+ }
32
+ async post(path, opts) {
33
+ return await this.request({
34
+ path,
35
+ method: HttpMethod.POST,
36
+ ...opts
37
+ });
38
+ }
39
+ async put(path, opts) {
40
+ return await this.request({
41
+ path,
42
+ method: HttpMethod.PUT,
43
+ ...opts
44
+ });
45
+ }
46
+ async delete(path, opts) {
47
+ return await this.request({
48
+ path,
49
+ method: HttpMethod.DELETE,
50
+ ...opts
51
+ });
52
+ }
53
+ async patch(path, opts) {
54
+ return await this.request({
55
+ path,
56
+ method: HttpMethod.PATCH,
57
+ ...opts
58
+ });
59
+ }
60
+ async request(opts) {
61
+ const activeContext = context.active();
62
+ const tracer = trace.getTracer(this.systemServiceName);
63
+ const baseUrl = opts.baseUrl || this.baseUrl;
64
+ if (!baseUrl) throw new Error("Base URL is not provided");
65
+ const span = tracer.startSpan(opts.method, {
66
+ kind: SpanKind.CLIENT,
67
+ attributes: {
68
+ [SEMATTRS_MESSAGING_SYSTEM]: RequestMechanism.Http,
69
+ [SemanticAttributes.HTTP_METHOD]: opts.method,
70
+ [SemanticAttributes.HTTP_URL]: `${baseUrl}${opts.path}`,
71
+ [SemanticAttributes.HTTP_TARGET]: opts.path,
72
+ "messaging.caller": this.systemServiceName
73
+ }
74
+ }, activeContext);
75
+ const { response, error, retryCount } = await this.requestHelper({
76
+ ...opts,
77
+ baseUrl
78
+ }, span);
79
+ span?.setAttribute("retryCount", retryCount);
80
+ if (response) {
81
+ const statusCode = response.status;
82
+ this.logger.info("HTTP request succeeded", {
83
+ statusCode,
84
+ path: opts.path,
85
+ method: opts.method
86
+ });
87
+ span?.setStatus({ code: SpanStatusCode.OK });
88
+ span?.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, statusCode);
89
+ span?.end();
90
+ return {
91
+ isOk: true,
92
+ statusCode,
93
+ headers: response.headers || {},
94
+ body: response.data
95
+ };
96
+ }
97
+ if (error) {
98
+ const { statusCode, originalError } = error;
99
+ this.logger.error("HTTP request failed", {
100
+ err: error,
101
+ method: opts.method,
102
+ path: opts.path,
103
+ statusCode
104
+ });
105
+ span?.setStatus({ code: SpanStatusCode.ERROR });
106
+ span?.recordException({
107
+ name: originalError.name || "Unexpected error",
108
+ message: originalError.message,
109
+ code: statusCode
110
+ });
111
+ span?.end();
112
+ return {
113
+ isOk: false,
114
+ statusCode,
115
+ body: originalError instanceof AxiosError ? originalError.response?.data : void 0,
116
+ headers: originalError instanceof AxiosError ? originalError.response?.headers || {} : {}
117
+ };
118
+ }
119
+ throw new Error("Unexpected error caused");
120
+ }
121
+ async requestHelper(opts, span, currentRequestRetries = 0) {
122
+ const timeout = opts.timeout || this.timeout;
123
+ const { method, path, baseUrl, query = {}, body, headers = {}, responseType = "json", retries = 0, retryInterval = 0, httpsAgent, httpAgent, errorType: errorTypeOps, metricLabel } = opts;
124
+ const startTime = process.hrtime.bigint();
125
+ span.addEvent("request", { message: `Started processing request. Retry count ${currentRequestRetries}` });
126
+ try {
127
+ const response = await axios.request({
128
+ method,
129
+ baseURL: baseUrl,
130
+ url: path,
131
+ params: query,
132
+ data: body,
133
+ headers,
134
+ responseType,
135
+ timeout,
136
+ httpsAgent,
137
+ httpAgent
138
+ });
139
+ this.observeSuccessRequest({
140
+ statusCode: response.status,
141
+ retryCount: currentRequestRetries,
142
+ startTime,
143
+ span,
144
+ baseUrl,
145
+ metricLabel
146
+ });
147
+ return {
148
+ response,
149
+ retryCount: currentRequestRetries
150
+ };
151
+ } catch (err) {
152
+ const statusCode = err?.response?.status || HttpStatusCode.INTERNAL_SERVER_ERROR;
153
+ const errorType = ErrorType.External || errorTypeOps;
154
+ this.observeFailedRequest({
155
+ statusCode,
156
+ retryCount: currentRequestRetries,
157
+ startTime,
158
+ span,
159
+ errorType,
160
+ baseUrl,
161
+ metricLabel
162
+ });
163
+ if (err instanceof AxiosError) {
164
+ if (currentRequestRetries < retries) {
165
+ this.logger.info("Retrying HTTP request", {
166
+ err,
167
+ path,
168
+ retries: currentRequestRetries + 1
169
+ });
170
+ return await waitAndRun(() => this.requestHelper(opts, span, currentRequestRetries + 1), retryInterval);
171
+ }
172
+ return {
173
+ error: new RequestError(err.message, statusCode, err),
174
+ retryCount: currentRequestRetries
175
+ };
176
+ }
177
+ return {
178
+ error: new OperationError("Internal package error", err),
179
+ retryCount: currentRequestRetries
180
+ };
181
+ }
182
+ }
183
+ observeSuccessRequest(params) {
184
+ const { statusCode, retryCount, startTime, span, baseUrl, metricLabel } = params;
185
+ const labels = this.getLabels(statusCode, RequestStatus.Successful, baseUrl, metricLabel);
186
+ span.addEvent("request", { message: `Finished processing request. Retry count ${retryCount}` });
187
+ this.metrics.totalTimerMetric.observeSeconds(labels, process.hrtime.bigint() - startTime);
188
+ }
189
+ observeFailedRequest(params) {
190
+ const { statusCode, retryCount, startTime, span, errorType, baseUrl, metricLabel } = params;
191
+ const labels = this.getLabels(statusCode, RequestStatus.Failed, baseUrl, metricLabel, errorType);
192
+ span.addEvent("request", { message: `Finished processing request. Retry count ${retryCount}` });
193
+ this.metrics.totalTimerMetric.observeSeconds(labels, process.hrtime.bigint() - startTime);
194
+ }
195
+ getLabels(statusCode, status, baseUrl, metricLabel, errorType) {
196
+ return {
197
+ status,
198
+ statusCode,
199
+ source: this.systemServiceName,
200
+ destination: `${baseUrl}|${metricLabel}`,
201
+ mechanism: RequestMechanism.Http,
202
+ ...errorType ? { errorType } : {}
203
+ };
204
+ }
205
+ };
206
+ //#endregion
207
+ export { HttpClientService };
@@ -0,0 +1,2 @@
1
+ import { HttpClientService } from "./httpClient.js";
2
+ import { checkServerIdentity } from "./utils.js";
@@ -1,21 +1,3 @@
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
- exports.checkServerIdentity = void 0;
18
- __exportStar(require("./httpClient"), exports);
19
- var utils_1 = require("./utils");
20
- Object.defineProperty(exports, "checkServerIdentity", { enumerable: true, get: function () { return utils_1.checkServerIdentity; } });
21
- //# sourceMappingURL=index.js.map
1
+ import "./utils.js";
2
+ import "./httpClient.js";
3
+ export {};
@@ -0,0 +1,6 @@
1
+ import { PeerCertificateWithSHA256 } from "@diia-inhouse/types";
2
+
3
+ //#region src/services/utils.d.ts
4
+ declare function checkServerIdentity(hostFingerprint: string): (host: string, cert: PeerCertificateWithSHA256) => Error | undefined;
5
+ //#endregion
6
+ export { checkServerIdentity };
@@ -1,22 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.waitAndRun = exports.sleep = void 0;
4
- exports.checkServerIdentity = checkServerIdentity;
5
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
- exports.sleep = sleep;
7
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1
+ import { setTimeout } from "node:timers/promises";
2
+ //#region src/services/utils.ts
3
+ const sleep = (ms) => setTimeout(ms);
8
4
  const waitAndRun = async (callback, ms) => {
9
- await (0, exports.sleep)(ms);
10
- return await callback();
5
+ await sleep(ms);
6
+ return await callback();
11
7
  };
12
- exports.waitAndRun = waitAndRun;
13
8
  function checkServerIdentity(hostFingerprint) {
14
- return (host, cert) => {
15
- const certFingerprint = cert.fingerprint256 || cert.fingerprint;
16
- if (!hostFingerprint || hostFingerprint === certFingerprint) {
17
- return;
18
- }
19
- return new Error(`Fingerprint for host ${host} does not match`);
20
- };
9
+ return (host, cert) => {
10
+ const certFingerprint = cert.fingerprint256 || cert.fingerprint;
11
+ if (!hostFingerprint || hostFingerprint === certFingerprint) return;
12
+ return /* @__PURE__ */ new Error(`Fingerprint for host ${host} does not match`);
13
+ };
21
14
  }
22
- //# sourceMappingURL=utils.js.map
15
+ //#endregion
16
+ export { checkServerIdentity, waitAndRun };
package/package.json CHANGED
@@ -1,25 +1,32 @@
1
1
  {
2
2
  "name": "@diia-inhouse/http",
3
- "version": "4.0.26",
3
+ "version": "5.1.0",
4
+ "type": "module",
4
5
  "description": "Wrapper to make http requests",
5
6
  "main": "dist/index.js",
6
- "types": "dist/types/index.d.ts",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
7
15
  "repository": "https://github.com/diia-open-source/be-pkg-http",
8
16
  "author": "Diia",
9
- "license": "SEE LICENSE IN LICENSE.md",
10
17
  "files": [
11
18
  "dist"
12
19
  ],
13
20
  "engines": {
14
- "node": ">=22"
21
+ "node": ">=24"
15
22
  },
16
23
  "scripts": {
17
24
  "prebuild": "rimraf dist",
18
- "build": "tsc",
25
+ "build": "tsdown",
19
26
  "semantic-release": "semantic-release",
20
27
  "start": "npm run build && node dist/index.js",
21
- "lint": "eslint . && prettier --check .",
22
- "lint-fix": "eslint --fix . && prettier --write .",
28
+ "lint": "oxlint && oxfmt --check .",
29
+ "lint-fix": "oxlint --fix && oxfmt .",
23
30
  "lint:lockfile": "lockfile-lint --path package-lock.json --allowed-hosts registry.npmjs.org --validate-https",
24
31
  "prepare": "npm run build",
25
32
  "test": "tsc --project tests/tsconfig.json --noEmit && vitest run",
@@ -30,42 +37,44 @@
30
37
  },
31
38
  "dependencies": {
32
39
  "await-to-js": "3.0.0",
33
- "axios": "1.15.0",
40
+ "axios": "1.16.0",
34
41
  "lodash": "4.18.1",
35
- "qs": "6.15.0"
42
+ "qs": "6.15.2"
36
43
  },
37
44
  "peerDependencies": {
38
- "@diia-inhouse/diia-metrics": ">=3.14.2",
39
- "@diia-inhouse/errors": ">=1.0.0",
40
- "@diia-inhouse/types": ">=1.0.0",
45
+ "@diia-inhouse/diia-metrics": ">=4.0.0",
46
+ "@diia-inhouse/errors": ">=2.0.0",
47
+ "@diia-inhouse/types": ">=13.1.0",
41
48
  "@opentelemetry/api": ">=1.9.0",
42
49
  "@opentelemetry/semantic-conventions": ">=1.28.0"
43
50
  },
44
51
  "devDependencies": {
45
52
  "@commitlint/cli": "19.7.1",
46
- "@diia-inhouse/configs": "6.1.1",
47
- "@diia-inhouse/diia-logger": "3.20.13",
48
- "@diia-inhouse/diia-metrics": "6.5.38",
49
- "@diia-inhouse/errors": "1.18.23",
50
- "@diia-inhouse/eslint-config": "8.8.2",
51
- "@diia-inhouse/test": "7.3.24",
52
- "@diia-inhouse/types": "11.7.0",
53
- "@opentelemetry/api": "1.9.0",
53
+ "@diia-inhouse/configs": "7.0.0",
54
+ "@diia-inhouse/diia-logger": "4.2.4",
55
+ "@diia-inhouse/diia-metrics": "7.1.5",
56
+ "@diia-inhouse/errors": "2.1.1",
57
+ "@diia-inhouse/oxc-config": "1.10.0",
58
+ "@diia-inhouse/test": "8.2.1",
59
+ "@diia-inhouse/types": "13.2.0",
60
+ "@opentelemetry/api": "1.9.1",
54
61
  "@opentelemetry/semantic-conventions": "1.40.0",
55
62
  "@types/lodash": "4.17.24",
56
- "@types/node": "25.3.3",
57
- "@vitest/coverage-v8": "4.0.18",
58
- "@vitest/ui": "4.0.18",
59
- "eslint": "9.31.0",
60
- "eslint-plugin-prettier": "5.2.3",
61
- "lockfile-lint": "4.14.1",
63
+ "@types/node": "25.6.2",
64
+ "@vitest/coverage-v8": "4.1.5",
65
+ "@vitest/ui": "4.1.5",
66
+ "lockfile-lint": "5.0.0",
62
67
  "madge": "8.0.0",
63
- "nock": "14.0.11",
68
+ "nock": "14.0.15",
69
+ "oxfmt": "0.48.0",
70
+ "oxlint": "1.63.0",
71
+ "oxlint-tsgolint": "0.22.1",
64
72
  "rimraf": "6.1.3",
65
- "semantic-release": "24.2.7",
73
+ "semantic-release": "25.0.3",
74
+ "tsdown": "0.22.0",
66
75
  "vite-tsconfig-paths": "6.1.1",
67
- "vitest": "4.0.18",
68
- "vitest-mock-extended": "3.1.0"
76
+ "vitest": "4.1.5",
77
+ "vitest-mock-extended": "4.0.0"
69
78
  },
70
79
  "overrides": {
71
80
  "form-data": "^4.0.4"
@@ -79,8 +88,8 @@
79
88
  "commitlint": {
80
89
  "extends": "@diia-inhouse/configs/dist/commitlint"
81
90
  },
82
- "prettier": "@diia-inhouse/eslint-config/prettier",
83
91
  "madge": {
84
92
  "tsConfig": "./tsconfig.json"
85
- }
93
+ },
94
+ "license": "SEE LICENSE IN LICENSE.md"
86
95
  }
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B;AAE1B,+CAA4B"}
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=deps.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/interfaces/deps.ts"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=httpClient.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"httpClient.js","sourceRoot":"","sources":["../../src/interfaces/httpClient.ts"],"names":[],"mappings":""}
@@ -1,19 +0,0 @@
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("./deps"), exports);
18
- __exportStar(require("./httpClient"), exports);
19
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAsB;AAEtB,+CAA4B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/errors/index.ts"],"names":[],"mappings":";;;AAAA,mDAAiD;AAAxC,gHAAA,cAAc,OAAA;AAEvB,+CAA6C;AAApC,4GAAA,YAAY,OAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"operationError.js","sourceRoot":"","sources":["../../../src/services/errors/operationError.ts"],"names":[],"mappings":";;;AAAA,+CAAoD;AAEpD,iDAA6C;AAE7C,MAAa,cAAe,SAAQ,2BAAY;IAC5C,YAAY,OAAe,EAAE,aAAoB;QAC7C,KAAK,CAAC,OAAO,EAAE,sBAAc,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAA;QAEnE,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAA;IAChC,CAAC;CACJ;AAND,wCAMC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"requestError.js","sourceRoot":"","sources":["../../../src/services/errors/requestError.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAa,SAAQ,KAAK;IAC1B,UAAU,CAAQ;IAElB,aAAa,CAAO;IAE7B,YAAY,OAAe,EAAE,UAAkB,EAAE,aAAoB;QACjE,KAAK,CAAC,OAAO,CAAC,CAAA;QAEd,IAAI,CAAC,IAAI,GAAG,cAAc,CAAA;QAC1B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACtC,CAAC;CACJ;AAZD,oCAYC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"httpClient.js","sourceRoot":"","sources":["../../src/services/httpClient.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+CAA4B;AAE5B,iCAA6C;AAApC,4GAAA,mBAAmB,OAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/services/utils.ts"],"names":[],"mappings":";;;AAWA,kDAUC;AAnBM,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAAxF,QAAA,KAAK,SAAmF;AAErG,8DAA8D;AACvD,MAAM,UAAU,GAAG,KAAK,EAA6C,QAAW,EAAE,EAAU,EAA0B,EAAE;IAC3H,MAAM,IAAA,aAAK,EAAC,EAAE,CAAC,CAAA;IAEf,OAAO,MAAM,QAAQ,EAAE,CAAA;AAC3B,CAAC,CAAA;AAJY,QAAA,UAAU,cAItB;AAED,SAAgB,mBAAmB,CAAC,eAAuB;IACvD,OAAO,CAAC,IAAY,EAAE,IAA+B,EAAE,EAAE;QACrD,MAAM,eAAe,GAAW,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,WAAW,CAAA;QAEvE,IAAI,CAAC,eAAe,IAAI,eAAe,KAAK,eAAe,EAAE,CAAC;YAC1D,OAAM;QACV,CAAC;QAED,OAAO,IAAI,KAAK,CAAC,wBAAwB,IAAI,iBAAiB,CAAC,CAAA;IACnE,CAAC,CAAA;AACL,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './services';
2
- export * from './interfaces';
@@ -1,4 +0,0 @@
1
- import { HttpClientService } from '../services';
2
- export type HttpDeps<TMetricLabel extends string> = {
3
- http?: HttpClientService<TMetricLabel>;
4
- };
@@ -1,73 +0,0 @@
1
- import { Agent as httpAgent } from 'node:http';
2
- import { Agent as httpsAgent } from 'node:https';
3
- import { Span } from '@opentelemetry/api';
4
- import { AxiosResponse, ResponseType } from 'axios';
5
- import { ErrorType } from '@diia-inhouse/errors';
6
- import { HttpMethod, HttpStatusCode } from '@diia-inhouse/types';
7
- import { OperationError, RequestError } from '../services/errors';
8
- export type ReadonlyQuery = Readonly<object>;
9
- /**
10
- * Enforces that T is a string literal or union of literals, not the broad `string` type.
11
- * Resolves to `never` if T is exactly `string`, causing a compile error.
12
- */
13
- type LowCardinality<T extends string> = string extends T ? never : T;
14
- export interface RequestOptions<TMetricLabel extends string> {
15
- baseUrl?: string;
16
- timeout?: number;
17
- retries?: number;
18
- retryInterval?: number;
19
- query?: ReadonlyQuery;
20
- headers?: Record<string, string>;
21
- body?: unknown;
22
- errorType?: ErrorType;
23
- responseType?: ResponseType;
24
- httpsAgent?: httpsAgent;
25
- httpAgent?: httpAgent;
26
- /**
27
- * Label used to separate metrics on the same destination host.
28
- *
29
- * **Must have low cardinality** — use a finite set of known values, not dynamic strings
30
- * like URLs, IDs, or user input. High-cardinality labels cause metric explosion and
31
- * degrade monitoring system performance.
32
- *
33
- * Define as a string union type to enforce allowed values at compile time:
34
- * @example
35
- * type MyMetricLabel = 'getUserProfile' | 'createOrder' | 'validateDocument'
36
- * const options: RequestOptions<MyMetricLabel> = { metricLabel: 'getUserProfile', ... }
37
- */
38
- metricLabel: LowCardinality<TMetricLabel>;
39
- }
40
- export interface FullRequestOptions<TMetricLabel extends string> extends RequestOptions<TMetricLabel> {
41
- path: string;
42
- method: HttpMethod;
43
- }
44
- export interface SuccessfulResponse<T> {
45
- isOk: true;
46
- statusCode: HttpStatusCode;
47
- headers?: Record<string, string>;
48
- body: T;
49
- }
50
- export interface FailureResponse<TError> {
51
- isOk: false;
52
- statusCode: HttpStatusCode;
53
- headers?: Record<string, string>;
54
- body: TError | undefined;
55
- }
56
- export type HttpClientResponse<TResponse, TError = unknown> = SuccessfulResponse<TResponse> | FailureResponse<TError>;
57
- export interface ObserveRequestBaseParams {
58
- statusCode: number;
59
- retryCount: number;
60
- startTime: bigint;
61
- span: Span;
62
- baseUrl: string;
63
- metricLabel: string;
64
- }
65
- export interface ObserveRequestFailedParams extends ObserveRequestBaseParams {
66
- errorType: ErrorType;
67
- }
68
- export interface RequestHelperResponse<TResponse> {
69
- response?: AxiosResponse<TResponse>;
70
- error?: RequestError | OperationError;
71
- retryCount: number;
72
- }
73
- export {};
@@ -1,2 +0,0 @@
1
- export * from './deps';
2
- export * from './httpClient';
@@ -1,2 +0,0 @@
1
- export { OperationError } from './operationError';
2
- export { RequestError } from './requestError';
@@ -1,4 +0,0 @@
1
- import { RequestError } from './requestError';
2
- export declare class OperationError extends RequestError {
3
- constructor(message: string, originalError: Error);
4
- }
@@ -1,5 +0,0 @@
1
- export declare class RequestError extends Error {
2
- readonly statusCode: number;
3
- readonly originalError: Error;
4
- constructor(message: string, statusCode: number, originalError: Error);
5
- }
@@ -1,21 +0,0 @@
1
- import { MetricsService } from '@diia-inhouse/diia-metrics';
2
- import { Logger } from '@diia-inhouse/types';
3
- import { HttpClientResponse, RequestOptions } from '../interfaces/httpClient';
4
- export declare class HttpClientService<TMetricLabel extends string> {
5
- private logger;
6
- private metrics;
7
- private readonly systemServiceName;
8
- private readonly timeout;
9
- private readonly baseUrl;
10
- constructor(logger: Logger, metrics: MetricsService, systemServiceName: string, timeout?: number, baseUrl?: string);
11
- get<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
12
- post<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
13
- put<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
14
- delete<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
15
- patch<TResponse, TError>(path: string, opts: RequestOptions<TMetricLabel>): Promise<HttpClientResponse<TResponse, TError>>;
16
- private request;
17
- private requestHelper;
18
- private observeSuccessRequest;
19
- private observeFailedRequest;
20
- private getLabels;
21
- }
@@ -1,2 +0,0 @@
1
- export * from './httpClient';
2
- export { checkServerIdentity } from './utils';
@@ -1,4 +0,0 @@
1
- import { PeerCertificateWithSHA256 } from '@diia-inhouse/types';
2
- export declare const sleep: (ms: number) => Promise<void>;
3
- export declare const waitAndRun: <T extends (...params: []) => Promise<any>>(callback: T, ms: number) => Promise<ReturnType<T>>;
4
- export declare function checkServerIdentity(hostFingerprint: string): (host: string, cert: PeerCertificateWithSHA256) => Error | undefined;