@vroskus/library-api 1.0.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.
@@ -0,0 +1,33 @@
1
+ import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ import AxiosMockAdapter from 'axios-mock-adapter';
3
+ import type { $Config, $RequestContext, $ResponseContext } from './types';
4
+ export * from './types';
5
+ type $RequestContextListener = (arg0: $RequestContext) => void;
6
+ type $SetRequestContextListenerParams = {
7
+ listener: $RequestContextListener;
8
+ };
9
+ type $SetRequestContextListenerResponse = void;
10
+ type $ResponseContextListener = (arg0: $ResponseContext) => void;
11
+ type $SetResponseContextListenerParams = {
12
+ listener: $ResponseContextListener;
13
+ };
14
+ type $SetResponseContextListenerResponse = void;
15
+ type $UnauthenticatedHandler = () => unknown;
16
+ type $SetUnauthenticatedHandlerParams = {
17
+ handler: $UnauthenticatedHandler;
18
+ };
19
+ type $SetUnauthenticatedHandlerResponse = void;
20
+ export declare const getMock: () => AxiosMockAdapter;
21
+ declare class ApiService<C extends $Config> {
22
+ connection: AxiosInstance;
23
+ unauthenticatedHandler: $UnauthenticatedHandler;
24
+ requestContextListener: $RequestContextListener;
25
+ responseContextListener: $ResponseContextListener;
26
+ constructor({ apiUrl, timeout, }: C);
27
+ setUnauthenticatedHandler({ handler, }: $SetUnauthenticatedHandlerParams): $SetUnauthenticatedHandlerResponse;
28
+ setRequestContextListener({ listener, }: $SetRequestContextListenerParams): $SetRequestContextListenerResponse;
29
+ setResponseContextListener({ listener, }: $SetResponseContextListenerParams): $SetResponseContextListenerResponse;
30
+ pushRequestContext(config: AxiosRequestConfig<unknown>, requestId: string): void;
31
+ pushResponseContext(response: AxiosResponse<unknown>): void;
32
+ }
33
+ export default ApiService;
package/dist/index.js ADDED
@@ -0,0 +1,127 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.getMock = void 0;
21
+ const axios_1 = __importDefault(require("axios"));
22
+ const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
23
+ const lodash_1 = __importDefault(require("lodash"));
24
+ const uuid_1 = require("uuid");
25
+ __exportStar(require("./types"), exports);
26
+ const getMock = () => new axios_mock_adapter_1.default(axios_1.default);
27
+ exports.getMock = getMock;
28
+ class ApiService {
29
+ constructor({ apiUrl, timeout, }) {
30
+ const connectionConfig = {
31
+ baseURL: apiUrl,
32
+ headers: {
33
+ Accept: 'application/json',
34
+ 'Content-Type': 'application/json',
35
+ },
36
+ timeout,
37
+ withCredentials: true,
38
+ };
39
+ this.connection = axios_1.default.create(connectionConfig);
40
+ this.unauthenticatedHandler = () => { };
41
+ this.requestContextListener = () => { };
42
+ this.responseContextListener = () => { };
43
+ this.connection.interceptors.response.use((response) => response, (error) => {
44
+ const status = lodash_1.default.get(error, 'response.status');
45
+ if (status === 401) {
46
+ this.unauthenticatedHandler();
47
+ }
48
+ return Promise.reject(error);
49
+ });
50
+ this.connection.interceptors.response.use((response) => {
51
+ this.pushResponseContext(response);
52
+ return response;
53
+ }, (error) => {
54
+ const response = lodash_1.default.get(error, 'response');
55
+ if (response) {
56
+ this.pushResponseContext(response);
57
+ }
58
+ return Promise.reject(error);
59
+ });
60
+ this.connection.interceptors.response.use(undefined, (error) => {
61
+ const message = lodash_1.default.get(error, 'message');
62
+ const config = lodash_1.default.get(error, 'config');
63
+ if (config
64
+ && config.retryQty !== 0
65
+ && ['Network Error', 'timeout'].some((e) => message.includes(e))) {
66
+ config.retryQty = typeof config.retryQty === 'undefined' ? 3 : config.retryQty - 1;
67
+ const delayRetryRequest = new Promise((resolve) => {
68
+ setTimeout(() => {
69
+ resolve(null);
70
+ }, config.retryDelay || 3000);
71
+ });
72
+ return delayRetryRequest.then(() => this.connection.request(config));
73
+ }
74
+ return Promise.reject(error);
75
+ });
76
+ this.connection.interceptors.request.use((config) => {
77
+ const requestId = (0, uuid_1.v4)();
78
+ lodash_1.default.set(config, 'headers.X-Request-Id', requestId);
79
+ const startTimestamp = performance.now();
80
+ lodash_1.default.set(config, 'startTimestamp', startTimestamp);
81
+ this.pushRequestContext(config, requestId);
82
+ return config;
83
+ });
84
+ }
85
+ setUnauthenticatedHandler({ handler, }) {
86
+ this.unauthenticatedHandler = handler;
87
+ }
88
+ setRequestContextListener({ listener, }) {
89
+ this.requestContextListener = listener;
90
+ }
91
+ setResponseContextListener({ listener, }) {
92
+ this.responseContextListener = listener;
93
+ }
94
+ pushRequestContext(config, requestId) {
95
+ const requestContext = {
96
+ Method: `${(config.method || 'Unknown').toUpperCase()}`,
97
+ RequestData: config.data,
98
+ RequestHeaders: config.headers,
99
+ RequestId: requestId,
100
+ RequestParams: config.params,
101
+ Route: config.url,
102
+ };
103
+ const cleanRequestContext = lodash_1.default.omitBy(requestContext, lodash_1.default.isUndefined);
104
+ this.requestContextListener(cleanRequestContext);
105
+ }
106
+ pushResponseContext(response) {
107
+ const requestId = lodash_1.default.get(response.config, 'headers.X-Request-Id', '');
108
+ const { config, data, headers, status, } = response;
109
+ const endTimestamp = performance.now();
110
+ const startTimestamp = lodash_1.default.get(config, 'startTimestamp', endTimestamp);
111
+ const responseContext = {
112
+ Duration: endTimestamp - startTimestamp,
113
+ Method: `${(config.method || 'Unknown').toUpperCase()}`,
114
+ RequestData: config.data,
115
+ RequestHeaders: config.headers,
116
+ RequestId: requestId,
117
+ RequestParams: config.params,
118
+ ResponseData: data,
119
+ ResponseHeaders: headers,
120
+ Route: config.url,
121
+ Status: status,
122
+ };
123
+ const cleanResponseContext = lodash_1.default.omitBy(responseContext, lodash_1.default.isUndefined);
124
+ this.responseContextListener(cleanResponseContext);
125
+ }
126
+ }
127
+ exports.default = ApiService;
@@ -0,0 +1,24 @@
1
+ export type $Config = {
2
+ apiUrl: string;
3
+ timeout: number;
4
+ };
5
+ export type $RequestContext = {
6
+ Method: string;
7
+ RequestData?: unknown;
8
+ RequestHeaders: unknown;
9
+ RequestId: string;
10
+ RequestParams?: Record<string, unknown>;
11
+ Route: string;
12
+ };
13
+ export type $ResponseContext = {
14
+ Duration: number;
15
+ Method: string;
16
+ RequestData?: Record<string, unknown>;
17
+ RequestHeaders: unknown;
18
+ RequestId: string;
19
+ RequestParams?: Record<string, unknown>;
20
+ ResponseData?: unknown;
21
+ ResponseHeaders: unknown;
22
+ Route: string;
23
+ Status: number;
24
+ };
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@vroskus/library-api",
3
+ "version": "1.0.0",
4
+ "description": "Api",
5
+ "author": "Vilius Roškus <vilius@regattas.eu>",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/vroskus/library-api.git"
10
+ },
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "files": [
14
+ "dist/"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "test": "npm run test:eslint && npm run test:e2e",
19
+ "test:eslint": "eslint src --fix",
20
+ "test:e2e": "echo 'No tests'"
21
+ },
22
+ "dependencies": {
23
+ "axios": "1.6.2",
24
+ "axios-mock-adapter": "1.22.0",
25
+ "lodash": "4.17.21",
26
+ "uuid": "9.0.1"
27
+ },
28
+ "devDependencies": {
29
+ "@types/jest": "29.5.7",
30
+ "@types/lodash": "4.14.200",
31
+ "@types/node": "20.8.10",
32
+ "@types/query-string": "6.3.0",
33
+ "@typescript-eslint/eslint-plugin": "6.9.1",
34
+ "@typescript-eslint/parser": "6.9.1",
35
+ "eslint": "8.53.0",
36
+ "eslint-config-airbnb-base": "15.0.0",
37
+ "eslint-config-airbnb-typescript": "17.1.0",
38
+ "eslint-plugin-import": "2.29.0",
39
+ "eslint-plugin-import-newlines": "1.3.4",
40
+ "eslint-plugin-react": "7.33.2",
41
+ "eslint-plugin-sort": "2.11.0",
42
+ "npm-check": "6.0.1",
43
+ "typescript": "5.2.2"
44
+ }
45
+ }