@contentstack/cli-utilities 0.1.1-beta.1

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 (52) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +40 -0
  3. package/.mocharc.json +12 -0
  4. package/.nycrc.json +5 -0
  5. package/LICENSE +21 -0
  6. package/lib/cli-error.js +16 -0
  7. package/lib/cli-ux.js +59 -0
  8. package/lib/config-handler.js +128 -0
  9. package/lib/flag-deprecation-check.js +40 -0
  10. package/lib/http-client/client.js +313 -0
  11. package/lib/http-client/http-response.js +46 -0
  12. package/lib/http-client/index.js +7 -0
  13. package/lib/index.js +17 -0
  14. package/lib/interfaces/index.js +2 -0
  15. package/lib/logger.js +92 -0
  16. package/lib/message-handler.js +43 -0
  17. package/lib/selectors/index.js +376 -0
  18. package/lib/selectors/interfaces.js +2 -0
  19. package/lib/selectors/validations.js +9 -0
  20. package/messages/auth.json +46 -0
  21. package/messages/config.json +9 -0
  22. package/messages/core.json +6 -0
  23. package/package.json +68 -0
  24. package/src/cli-error.ts +15 -0
  25. package/src/cli-ux.ts +78 -0
  26. package/src/config-handler.ts +142 -0
  27. package/src/flag-deprecation-check.ts +41 -0
  28. package/src/http-client/client.ts +369 -0
  29. package/src/http-client/http-response.ts +55 -0
  30. package/src/http-client/index.ts +7 -0
  31. package/src/index.ts +7 -0
  32. package/src/interfaces/index.ts +61 -0
  33. package/src/logger.ts +101 -0
  34. package/src/message-handler.ts +45 -0
  35. package/src/selectors/index.ts +381 -0
  36. package/src/selectors/interfaces.ts +39 -0
  37. package/src/selectors/validations.ts +5 -0
  38. package/test/helpers/init.js +4 -0
  39. package/test/tsconfig.json +6 -0
  40. package/tsconfig.json +20 -0
  41. package/types/cli-error.d.ts +4 -0
  42. package/types/cli-ux.d.ts +22 -0
  43. package/types/config-handler.d.ts +17 -0
  44. package/types/flag-deprecation-check.d.ts +7 -0
  45. package/types/http-client.d.ts +54 -0
  46. package/types/index.d.ts +7 -0
  47. package/types/interfaces/index.d.ts +50 -0
  48. package/types/logger.d.ts +17 -0
  49. package/types/message-handler.d.ts +12 -0
  50. package/types/selectors/index.d.ts +12 -0
  51. package/types/selectors/interfaces.d.ts +32 -0
  52. package/types/selectors/validations.d.ts +1 -0
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@contentstack/cli-utilities",
3
+ "version": "0.1.1-beta.1",
4
+ "description": "Utilities for contentstack projects",
5
+ "main": "lib/index.js",
6
+ "types": "./types/index.d.ts",
7
+ "scripts": {
8
+ "prepack": "npm run clean && npm run compile",
9
+ "clean": "rm -rf ./lib && rm -rf tsconfig.build.tsbuildinfo",
10
+ "compile": "tsc -b tsconfig.json",
11
+ "test:report": "tsc -p test && nyc --reporter=lcov --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
12
+ "pretest": "tsc -p test",
13
+ "test": "nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
14
+ "posttest": "npm run lint",
15
+ "lint": "eslint src/**/*.ts",
16
+ "format": "eslint src/**/*.ts --fix"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": ""
21
+ },
22
+ "keywords": [
23
+ "contentstack",
24
+ "utilities"
25
+ ],
26
+ "author": "contentstack",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "@contentstack/management": "^1.3.0",
30
+ "@oclif/core": "^1.8.2",
31
+ "axios": "^0.27.2",
32
+ "chalk": "^4.0.0",
33
+ "conf": "^10.1.2",
34
+ "debug": "^4.1.1",
35
+ "inquirer": "^8.0.0",
36
+ "ora": "^5.4.0",
37
+ "winston": "^3.7.2"
38
+ },
39
+ "devDependencies": {
40
+ "@oclif/plugin-help": "^5.1.12",
41
+ "@oclif/test": "^1.2.8",
42
+ "@types/axios": "^0.14.0",
43
+ "@types/chai": "^4.2.18",
44
+ "@types/conf": "^3.0.0",
45
+ "@types/dot-prop": "^5.0.1",
46
+ "@types/inquirer": "^7.3.1",
47
+ "@types/mkdirp": "^1.0.1",
48
+ "@types/mocha": "^8.2.2",
49
+ "@types/nock": "^11.1.0",
50
+ "@types/node": "^14.14.32",
51
+ "@types/sinon": "^10.0.2",
52
+ "@types/tar": "^4.0.3",
53
+ "@types/winston": "^2.4.4",
54
+ "chai": "^4.3.4",
55
+ "eslint": "^8.18.0",
56
+ "eslint-config-oclif": "^3.1.0",
57
+ "eslint-config-oclif-typescript": "^0.1.0",
58
+ "globby": "^10.0.2",
59
+ "mocha": "^9.2.2",
60
+ "nock": "^13.1.0",
61
+ "nyc": "^15.1.0",
62
+ "rimraf": "^2.7.1",
63
+ "sinon": "^11.1.1",
64
+ "tmp": "^0.2.1",
65
+ "ts-node": "^8.10.2",
66
+ "typescript": "^4.7.4"
67
+ }
68
+ }
@@ -0,0 +1,15 @@
1
+ export default class CLIError extends Error {
2
+ suggestions?: string[];
3
+
4
+ constructor(message, suggestions?: string[]) {
5
+ super(message);
6
+ this.suggestions = suggestions;
7
+ this.message = message;
8
+
9
+ if (typeof Error.captureStackTrace === 'function') {
10
+ Error.captureStackTrace(this, this.constructor);
11
+ } else {
12
+ this.stack = new Error(message).stack;
13
+ }
14
+ }
15
+ }
package/src/cli-ux.ts ADDED
@@ -0,0 +1,78 @@
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+ import { ux as cliux, Table } from '@oclif/core/lib/cli-ux'
4
+
5
+ import messageHandler from './message-handler';
6
+ import { PrintOptions, InquirePayload, CliUXPromptOptions } from './interfaces';
7
+
8
+ /**
9
+ * CLI Interface
10
+ */
11
+ class CLIInterface {
12
+ private loading: boolean;
13
+
14
+ constructor() {
15
+ this.loading = false;
16
+ }
17
+
18
+ get uxTable(): typeof Table.table {
19
+ return cliux.table
20
+ }
21
+
22
+ init(context) {}
23
+
24
+ print(message: string, opts?: PrintOptions): void {
25
+ if (opts && opts.color) {
26
+ cliux.log(chalk[opts.color](messageHandler.parse(message)));
27
+ return;
28
+ }
29
+
30
+ cliux.log(messageHandler.parse(message));
31
+ }
32
+
33
+ success(message: string): void {
34
+ cliux.log(chalk.green(messageHandler.parse(message)));
35
+ }
36
+
37
+ error(message: string, ...params: any): void {
38
+ cliux.log(chalk.red(messageHandler.parse(message) + (params && params.length > 0 ? ': ' : '')), ...params);
39
+ }
40
+
41
+ loader(message: string = ''): void {
42
+ if (!this.loading) {
43
+ cliux.action.start(messageHandler.parse(message));
44
+ } else {
45
+ cliux.action.stop(messageHandler.parse(message));
46
+ }
47
+ this.loading = !this.loading;
48
+ }
49
+
50
+ table(
51
+ data: Record<string, unknown>[],
52
+ columns: Table.table.Columns<Record<string, unknown>>,
53
+ options?: Table.table.Options
54
+ ): void {
55
+ cliux.table(data, columns, options);
56
+ }
57
+
58
+ async inquire<T>(inquirePayload: InquirePayload): Promise<T> {
59
+ inquirePayload.message = messageHandler.parse(inquirePayload.message);
60
+ const result = await inquirer.prompt(inquirePayload as inquirer.QuestionCollection<T>);
61
+
62
+ return result[inquirePayload.name] as T;
63
+ }
64
+
65
+ prompt(name: string, options?: CliUXPromptOptions): Promise<any> {
66
+ return cliux.prompt(name, options)
67
+ }
68
+
69
+ confirm(message?: string): Promise<boolean> {
70
+ return cliux.confirm(message)
71
+ }
72
+
73
+ progress(options?: any): any {
74
+ return cliux.progress(options)
75
+ }
76
+ }
77
+
78
+ export default new CLIInterface();
@@ -0,0 +1,142 @@
1
+ import Conf from 'conf';
2
+ import { v4 as uuid } from 'uuid';
3
+ import { existsSync, unlinkSync } from 'fs'
4
+
5
+ const ENC_KEY = 'encryptionKey';
6
+ const ENCRYPT_CONF: boolean = true
7
+ const CONFIG_NAME = 'contentstack_cli';
8
+ const ENC_CONFIG_NAME = 'contentstack_cli_obfuscate';
9
+
10
+ class Config {
11
+ private config: Conf;
12
+
13
+ constructor() {
14
+ this.init()
15
+ }
16
+
17
+ init() {
18
+ return ENCRYPT_CONF === true
19
+ ? this.getEncryptedConfig()
20
+ : this.getDecryptedConfig()
21
+ }
22
+
23
+ private fallbackInit(): Conf {
24
+ return new Conf({ configName: CONFIG_NAME, encryptionKey: ENC_KEY })
25
+ }
26
+
27
+ private getObfuscationKey() {
28
+ const obfuscationKeyName = 'obfuscation_key'
29
+ const encConfig = new Conf({ configName: ENC_CONFIG_NAME })
30
+ let obfuscationKey: any = encConfig.get(obfuscationKeyName)
31
+
32
+ if (!obfuscationKey) {
33
+ encConfig.set(obfuscationKeyName, uuid())
34
+ obfuscationKey = encConfig.get(obfuscationKeyName)
35
+ }
36
+
37
+ return obfuscationKey
38
+ }
39
+
40
+ private getConfigDataAndUnlinkConfigFile(config: Conf) {
41
+ let configData
42
+
43
+ if (config?.path) {
44
+ if (existsSync(config.path)) {
45
+ configData = JSON.parse(JSON.stringify(config?.store || {})) // NOTE convert prototype object to plain object
46
+ unlinkSync(config.path) // NOTE remove old config file
47
+ }
48
+ }
49
+
50
+ return configData
51
+ }
52
+
53
+ private getEncryptedConfig(configData?: Record<string, unknown>, skip = false) {
54
+ const getEncryptedDataElseFallBack = () => {
55
+ try {
56
+ // NOTE reading current code base encrypted file if exist
57
+ const encryptionKey: any = this.getObfuscationKey()
58
+ this.config = new Conf({ configName: CONFIG_NAME, encryptionKey })
59
+
60
+ if (Object.keys(configData || {})?.length) {
61
+ this.config.set(configData) // NOTE set config data if passed any
62
+ }
63
+ } catch (error) {
64
+ // NOTE reading old code base encrypted file if exist
65
+ try {
66
+ const config = this.fallbackInit()
67
+ const configData = this.getConfigDataAndUnlinkConfigFile(config)
68
+ this.getEncryptedConfig(configData, true)
69
+ } catch (error) {
70
+ // console.trace(error.message)
71
+ }
72
+ }
73
+ }
74
+
75
+ try {
76
+ if (skip === false) {
77
+ const config = new Conf({ configName: CONFIG_NAME })
78
+ const configData = this.getConfigDataAndUnlinkConfigFile(config)
79
+ this.getEncryptedConfig(configData, true)
80
+ } else {
81
+ getEncryptedDataElseFallBack()
82
+ }
83
+ } catch (error) {
84
+ // console.trace(error.message)
85
+ // NOTE reading current code base encrypted file if exist
86
+ getEncryptedDataElseFallBack()
87
+ }
88
+
89
+ return this.config
90
+ }
91
+
92
+ private getDecryptedConfig(configData?: Record<string, unknown>) {
93
+ try {
94
+ this.config = new Conf({ configName: CONFIG_NAME })
95
+
96
+ if (Object.keys(configData || {})?.length) {
97
+ this.config.set(configData) // NOTE set config data if passed any
98
+ }
99
+ } catch (error) {
100
+ // console.trace(error.message)
101
+
102
+ try {
103
+ const encryptionKey: any = this.getObfuscationKey()
104
+ let config = new Conf({ configName: CONFIG_NAME, encryptionKey })
105
+ const configData = this.getConfigDataAndUnlinkConfigFile(config)
106
+ this.getDecryptedConfig(configData) // NOTE NOTE reinitialize the config with old data and new decrypted file
107
+ } catch (error) {
108
+ // console.trace(error.message)
109
+
110
+ try {
111
+ const config = this.fallbackInit()
112
+ const configData = this.getConfigDataAndUnlinkConfigFile(config)
113
+ this.getDecryptedConfig(configData) // NOTE reinitialize the config with old data and new decrypted file
114
+ } catch (error) {
115
+ // console.trace(error.message)
116
+ }
117
+ }
118
+ }
119
+
120
+ return this.config
121
+ }
122
+
123
+ get(key): string | any {
124
+ return this.config.get(key);
125
+ }
126
+
127
+ async set(key, value) {
128
+ this.config.set(key, value);
129
+ return this.config;
130
+ }
131
+
132
+ delete(key) {
133
+ this.config.delete(key);
134
+ return this.config;
135
+ }
136
+
137
+ clear() {
138
+ this.config.clear()
139
+ }
140
+ }
141
+
142
+ export default new Config();
@@ -0,0 +1,41 @@
1
+ import cliux from './cli-ux';
2
+
3
+ /**
4
+ * checks the deprecation and prints it
5
+ * @param {Array} deprecatedFlags flags to be deprecated
6
+ * @param {String} customMessage [optional] a custom message
7
+ * @returns flag parser
8
+ */
9
+ export default function (deprecatedFlags = [], suggestions = [], customMessage?: string) {
10
+ return (input, command) => {
11
+ const { context: { flagWarningPrintState = {} } = {} } = command
12
+ let isCommandHasDeprecationFlag = false;
13
+ deprecatedFlags.forEach((item) => {
14
+ if (command.argv.indexOf(item) !== -1) {
15
+ if (flagWarningPrintState[command.id + item]) {
16
+ return input
17
+ }
18
+ flagWarningPrintState[command.id + item] = true
19
+ isCommandHasDeprecationFlag = true;
20
+ }
21
+ });
22
+
23
+ if (isCommandHasDeprecationFlag) {
24
+ let depreactionMessage = '';
25
+ if (customMessage) {
26
+ depreactionMessage = customMessage;
27
+ } else {
28
+ depreactionMessage = `WARNING!!! You're using the old (soon to be deprecated) Contentstack CLI flags (${deprecatedFlags.join(
29
+ ', ',
30
+ )}).`;
31
+
32
+ if (suggestions.length > 0) {
33
+ depreactionMessage += ` We recommend you to use the updated flags (${suggestions.join(', ')}).`;
34
+ }
35
+ }
36
+ cliux.print(depreactionMessage, { color: 'yellow' });
37
+ }
38
+
39
+ return input;
40
+ };
41
+ }
@@ -0,0 +1,369 @@
1
+ import Axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ import { HttpResponse } from './http-response';
3
+
4
+ export class HttpClient {
5
+ /**
6
+ * The request configuration.
7
+ */
8
+ private request: AxiosRequestConfig;
9
+
10
+ /**
11
+ * The request configuration.
12
+ */
13
+ private readonly axiosInstance: AxiosInstance;
14
+
15
+ /**
16
+ * The payload format for a JSON or form-url-encoded request.
17
+ */
18
+ private bodyFormat: BodyFormat = 'json';
19
+
20
+ /**
21
+ * Createa new pending HTTP request instance.
22
+ */
23
+ constructor() {
24
+ this.request = {};
25
+ this.axiosInstance = Axios.create();
26
+
27
+ // Sets payload format as json by default
28
+ this.asJson();
29
+ }
30
+
31
+ /**
32
+ * Create a reusable HttpClient instance.
33
+ *
34
+ * @returns {HttpClient}
35
+ */
36
+ static create(): HttpClient {
37
+ return new this();
38
+ }
39
+
40
+ /**
41
+ * Returns the Axios request config.
42
+ *
43
+ * @returns {AxiosRequestConfig}
44
+ */
45
+ requestConfig(): AxiosRequestConfig {
46
+ return this.request;
47
+ }
48
+
49
+ /**
50
+ * Resets the request config.
51
+ *
52
+ * @returns {AxiosRequestConfig}
53
+ */
54
+ resetConfig(): HttpClient {
55
+ this.request = {};
56
+ return this;
57
+ }
58
+
59
+ /**
60
+ * Use the given `baseUrl` for all requests.
61
+ *
62
+ * @param {String} baseUrl
63
+ *
64
+ * @returns {HttpClient}
65
+ */
66
+ baseUrl(baseUrl: string): HttpClient {
67
+ if (typeof baseUrl !== 'string') {
68
+ throw new Error(`The base URL must be a string. Received "${typeof baseUrl}"`);
69
+ }
70
+
71
+ this.request.baseURL = baseUrl;
72
+
73
+ return this;
74
+ }
75
+
76
+ /**
77
+ * Add request headers.
78
+ * @returns {HttpClient}
79
+ */
80
+ headers(headers: any): HttpClient {
81
+ this.request.headers = { ...this.request.headers, ...headers };
82
+
83
+ return this;
84
+ }
85
+
86
+ /**
87
+ * Add query parameters to the request.
88
+ *
89
+ * @param {Object} queryParams
90
+ *
91
+ * @returns {HttpClient}
92
+ */
93
+ queryParams(queryParams: object): HttpClient {
94
+ this.request.params = { ...this.request.params, ...queryParams };
95
+
96
+ return this;
97
+ }
98
+
99
+ /**
100
+ * Add basic authentication via `username` and `password` to the request.
101
+ *
102
+ * @param {String} username
103
+ * @param {String} password
104
+ *
105
+ * @returns {HttpClient}
106
+ */
107
+ basicAuth(username: string, password: string): HttpClient {
108
+ this.request.auth = { username, password };
109
+
110
+ return this;
111
+ }
112
+
113
+ /**
114
+ * Add an authorization `token` to the request.
115
+ *
116
+ * @param {String} token
117
+ * @param {String} type
118
+ *
119
+ * @returns {HttpClient}
120
+ */
121
+ token(token: string, type: string = 'Bearer'): HttpClient {
122
+ return this.headers({
123
+ Authorization: `${type} ${token}`.trim(),
124
+ });
125
+ }
126
+
127
+ /**
128
+ * Merge your own custom Axios options into the request.
129
+ *
130
+ * @param {Object} options
131
+ *
132
+ * @returns {HttpClient}
133
+ */
134
+ options(options: AxiosRequestConfig = {}): HttpClient {
135
+ Object.assign(this.request, options);
136
+
137
+ return this;
138
+ }
139
+
140
+ /**
141
+ * Add a request payload.
142
+ *
143
+ * @param {*} data
144
+ *
145
+ * @returns {HttpClient}
146
+ */
147
+ payload(data: any): HttpClient {
148
+ this.request.data = data;
149
+
150
+ return this;
151
+ }
152
+
153
+ /**
154
+ * Define the request `timeout` in milliseconds.
155
+ *
156
+ * @param {Number} timeout
157
+ *
158
+ * @returns {HttpClient}
159
+ */
160
+ timeout(timeout: number): HttpClient {
161
+ this.request.timeout = timeout;
162
+
163
+ return this;
164
+ }
165
+
166
+ /**
167
+ * Tell HttpClient to send the request as JSON payload.
168
+ *
169
+ * @returns {HttpClient}
170
+ */
171
+ asJson(): HttpClient {
172
+ return this.payloadFormat('json').contentType('application/json');
173
+ }
174
+
175
+ /**
176
+ * Tell HttpClient to send the request as form parameters,
177
+ * encoded as URL query parameters.
178
+ *
179
+ * @returns {HttpClient}
180
+ */
181
+ asFormParams(): HttpClient {
182
+ return this.payloadFormat('formParams').contentType('application/x-www-form-urlencoded');
183
+ }
184
+
185
+ /**
186
+ * Set the request payload format.
187
+ *
188
+ * @param {String} format
189
+ *
190
+ * @returns {HttpClient}
191
+ */
192
+ payloadFormat(format: BodyFormat): HttpClient {
193
+ this.bodyFormat = format;
194
+
195
+ return this;
196
+ }
197
+
198
+ /**
199
+ * Set the `Accept` request header. This indicates what
200
+ * content type the server should return.
201
+ *
202
+ * @param {String} accept
203
+ *
204
+ * @returns {HttpClient}
205
+ */
206
+ accept(accept: string): HttpClient {
207
+ return this.headers({ Accept: accept });
208
+ }
209
+
210
+ /**
211
+ * Set the `Accept` request header to JSON. This indicates
212
+ * that the server should return JSON data.
213
+ *
214
+ * @param {String} accept
215
+ *
216
+ * @returns {HttpClient}
217
+ */
218
+ acceptJson(): HttpClient {
219
+ return this.accept('application/json');
220
+ }
221
+
222
+ /**
223
+ * Set the `Content-Type` request header.
224
+ *
225
+ * @param {String} contentType
226
+ *
227
+ * @returns {HttpClient}
228
+ */
229
+ contentType(contentType: string): HttpClient {
230
+ return this.headers({ 'Content-Type': contentType });
231
+ }
232
+
233
+ /**
234
+ * Send an HTTP GET request, optionally with the given `queryParams`.
235
+ *
236
+ * @param {String} url
237
+ * @param {Object} queryParams
238
+ *
239
+ * @returns {HttpResponse}
240
+ *
241
+ * @throws
242
+ */
243
+ async get<R>(url: string, queryParams: object = {}): Promise<HttpResponse<R>> {
244
+ this.queryParams(queryParams);
245
+
246
+ return this.send<R>('GET', url);
247
+ }
248
+
249
+ /**
250
+ * Send an HTTP POST request, optionally with the given `payload`.
251
+ *
252
+ * @param {String} url
253
+ * @param {Object} payload
254
+ *
255
+ * @returns {HttpResponse}
256
+ *
257
+ * @throws
258
+ */
259
+ async post<R>(url: string, payload?: any): Promise<HttpResponse<R>> {
260
+ if (payload) {
261
+ this.payload(payload);
262
+ }
263
+
264
+ return this.send<R>('POST', url);
265
+ }
266
+
267
+ /**
268
+ * Send an HTTP PUT request, optionally with the given `payload`.
269
+ *
270
+ * @param {String} url
271
+ * @param {Object} payload
272
+ *
273
+ * @returns {HttpResponse}
274
+ *
275
+ * @throws
276
+ */
277
+ async put<R>(url: string, payload?: any): Promise<HttpResponse<R>> {
278
+ if (payload) {
279
+ this.payload(payload);
280
+ }
281
+
282
+ return this.send<R>('PUT', url);
283
+ }
284
+
285
+ /**
286
+ * Send an HTTP PATCH request, optionally with the given `payload`.
287
+ *
288
+ * @param {String} url
289
+ * @param {Object} payload
290
+ *
291
+ * @returns {HttpResponse}
292
+ *
293
+ * @throws
294
+ */
295
+ async patch<R>(url: string, payload?: any): Promise<HttpResponse<R>> {
296
+ if (payload) {
297
+ this.payload(payload);
298
+ }
299
+
300
+ return this.send<R>('PATCH', url);
301
+ }
302
+
303
+ /**
304
+ * Send an HTTP DELETE request, optionally with the given `queryParams`.
305
+ *
306
+ * @param {String} url
307
+ * @param {Object} queryParams
308
+ *
309
+ * @returns {HttpResponse}
310
+ *
311
+ * @throws
312
+ */
313
+ async delete<R>(url: string, queryParams: object = {}): Promise<HttpResponse<R>> {
314
+ this.queryParams(queryParams);
315
+
316
+ return this.send<R>('DELETE', url);
317
+ }
318
+
319
+ /**
320
+ * Send the HTTP request.
321
+ *
322
+ * @param {String} method
323
+ * @param {String} url
324
+ *
325
+ * @returns {HttpResponse}
326
+ *
327
+ * @throws
328
+ */
329
+ async send<R>(method: HttpMethod, url: string): Promise<HttpResponse<R>> {
330
+ try {
331
+ return new HttpResponse<R>(await this.createAndSendRequest(method, url));
332
+ } catch (error: any) {
333
+ if (error.response) {
334
+ return new HttpResponse(error.response);
335
+ }
336
+
337
+ throw error;
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Create and send the HTTP request.
343
+ *
344
+ * @param {String} method
345
+ * @param {String} url
346
+ *
347
+ * @returns {Request}
348
+ */
349
+ async createAndSendRequest(method: HttpMethod, url: string): Promise<AxiosResponse> {
350
+ return await this.axiosInstance({
351
+ url,
352
+ method,
353
+ withCredentials: true,
354
+ ...this.request,
355
+ data: this.prepareRequestPayload(),
356
+ });
357
+ }
358
+
359
+ /**
360
+ * Returns the request payload depending on the selected request payload format.
361
+ */
362
+ prepareRequestPayload(): any {
363
+ return this.bodyFormat === 'formParams' ? new URLSearchParams(this.request.data).toString() : this.request.data;
364
+ }
365
+ }
366
+
367
+ type BodyFormat = 'json' | 'formParams';
368
+
369
+ type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS';