@mablhq/mabl-cli 1.13.14 → 1.13.17

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.
@@ -28,9 +28,12 @@ const httpUtil_1 = require("../util/httpUtil");
28
28
  const axios_1 = __importDefault(require("axios"));
29
29
  const os = __importStar(require("os"));
30
30
  const async_retry_1 = __importDefault(require("async-retry"));
31
+ const logUtils_1 = require("../util/logUtils");
31
32
  const asyncUtil_1 = require("../util/asyncUtil");
32
33
  const MABL_ENTITY_VERSION_HEADER = 'x-mabl-entity-version';
33
- const DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS = 300000;
34
+ const DEFAULT_REQUEST_TIMEOUT_MILLISECONDS = 60000;
35
+ const DEFAULT_RETRIES = 5;
36
+ const DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS = DEFAULT_REQUEST_TIMEOUT_MILLISECONDS * DEFAULT_RETRIES;
34
37
  const DEFAULT_MIN_RETRY_TIMEOUT_MILLISECONDS = 100;
35
38
  const DEFAULT_MAX_RETRY_TIMEOUT_MILLISECONDS = 1000;
36
39
  var AuthType;
@@ -40,10 +43,12 @@ var AuthType;
40
43
  })(AuthType = exports.AuthType || (exports.AuthType = {}));
41
44
  class BasicApiClient {
42
45
  constructor(options) {
46
+ var _a, _b;
43
47
  const config = httpUtil_1.axiosProxyConfig({
44
48
  sslVerify: options.sslVerify,
45
49
  proxyHost: options.proxyUrl,
46
50
  });
51
+ config.timeout = (_a = options.requestTimeoutMillis) !== null && _a !== void 0 ? _a : DEFAULT_REQUEST_TIMEOUT_MILLISECONDS;
47
52
  switch (options.authType) {
48
53
  case AuthType.ApiKey:
49
54
  config.auth = {
@@ -70,21 +75,22 @@ class BasicApiClient {
70
75
  }
71
76
  this.httpClient = axios_1.default.create(config);
72
77
  this.retryConfig = options.retryConfig;
78
+ this.debugLogger = (_b = options.debugLogger) !== null && _b !== void 0 ? _b : logUtils_1.logInternal;
73
79
  }
74
- async makeGetRequest(path) {
75
- return this.retryWrappedRequest(async () => this.getRequest(path));
80
+ makeGetRequest(path) {
81
+ return this.retryWrappedRequest(`makeGetRequest('${path}')`, () => this.getRequest(path));
76
82
  }
77
83
  async getRequest(path) {
78
- const response = await this.httpClient.get(path);
84
+ const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
79
85
  BasicApiClient.checkResponseStatusCode(response);
80
86
  return response.data;
81
87
  }
82
- async makeGetRequestWithETag(path) {
83
- return this.retryWrappedRequest(async () => this.getRequestWithETag(path));
88
+ makeGetRequestWithETag(path) {
89
+ return this.retryWrappedRequest(`makeGetRequestWithETag('${path}')`, () => this.getRequestWithETag(path));
84
90
  }
85
91
  async getRequestWithETag(path) {
86
92
  var _a;
87
- const response = await this.httpClient.get(path);
93
+ const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
88
94
  BasicApiClient.checkResponseStatusCode(response);
89
95
  const headers = response.headers;
90
96
  const result = response.data;
@@ -95,42 +101,63 @@ class BasicApiClient {
95
101
  return { ...result, entity_version: versionHeader };
96
102
  }
97
103
  async makePostRequest(path, requestBody, requestConfig) {
98
- const response = await this.httpClient.post(path, requestBody, requestConfig);
104
+ const response = await this.debugRequest('POST', path, () => this.httpClient.post(path, requestBody, requestConfig));
99
105
  BasicApiClient.checkResponseStatusCode(response);
100
106
  return response.data;
101
107
  }
102
108
  async makePutRequest(path, requestBody) {
103
- const response = await this.httpClient.put(path, requestBody);
109
+ const response = await this.debugRequest('PUT', path, () => this.httpClient.put(path, requestBody));
104
110
  BasicApiClient.checkResponseStatusCode(response);
105
111
  return response.data;
106
112
  }
107
- async makeDeleteRequest(path) {
108
- return this.retryWrappedRequest(async () => this.deleteRequest(path));
113
+ makeDeleteRequest(path) {
114
+ return this.retryWrappedRequest(`makeDeleteRequest('${path}')`, () => this.deleteRequest(path));
109
115
  }
110
116
  async deleteRequest(path) {
111
- const response = await this.httpClient.delete(path);
117
+ const response = await this.debugRequest('DELETE', path, () => this.deleteRequest(path));
112
118
  BasicApiClient.checkResponseStatusCode(response);
113
119
  return response.data;
114
120
  }
115
121
  async makePatchRequest(path, requestBody, ifMatch) {
116
122
  const extraConfig = ifMatch ? { headers: { 'If-Match': ifMatch } } : {};
117
- const response = await this.httpClient.patch(path, requestBody, extraConfig);
123
+ const response = await this.debugRequest('PATCH', path, () => this.httpClient.patch(path, requestBody, extraConfig));
118
124
  BasicApiClient.checkResponseStatusCode(response);
119
125
  return response.data;
120
126
  }
127
+ async debugRequest(method, path, request) {
128
+ const startTimeMillis = Date.now();
129
+ let responseCode;
130
+ let error;
131
+ try {
132
+ this.debugLogger(`API Client: Sending ${method} ${path}`);
133
+ const response = await request();
134
+ responseCode = response.status;
135
+ return response;
136
+ }
137
+ catch (e) {
138
+ error = e;
139
+ throw e;
140
+ }
141
+ finally {
142
+ this.debugLogger(`API Client: ${method} ${path} ${error ? 'failed' : 'completed'} in ${Date.now() - startTimeMillis}ms with ${responseCode !== null && responseCode !== void 0 ? responseCode : error}`);
143
+ }
144
+ }
121
145
  static checkResponseStatusCode(response) {
122
146
  const statusCode = response.status;
123
147
  if (!statusCode || statusCode >= 400) {
124
148
  throw new ApiError_1.ApiError(`[${statusCode} - ${response.statusText}]`, statusCode);
125
149
  }
126
150
  }
127
- retryWrappedRequest(requestFunc) {
151
+ retryWrappedRequest(description, requestFunc) {
128
152
  var _a, _b, _c, _d, _e, _f, _g, _h;
129
153
  const retryOptions = {
130
- retries: (_b = (_a = this.retryConfig) === null || _a === void 0 ? void 0 : _a.retryCount) !== null && _b !== void 0 ? _b : 0,
154
+ retries: (_b = (_a = this.retryConfig) === null || _a === void 0 ? void 0 : _a.retryCount) !== null && _b !== void 0 ? _b : DEFAULT_RETRIES,
131
155
  minTimeout: (_d = (_c = this.retryConfig) === null || _c === void 0 ? void 0 : _c.minTimeoutMillis) !== null && _d !== void 0 ? _d : DEFAULT_MIN_RETRY_TIMEOUT_MILLISECONDS,
132
156
  maxTimeout: (_f = (_e = this.retryConfig) === null || _e === void 0 ? void 0 : _e.maxTimeoutMillis) !== null && _f !== void 0 ? _f : DEFAULT_MAX_RETRY_TIMEOUT_MILLISECONDS,
133
157
  maxRetryTime: (_h = (_g = this.retryConfig) === null || _g === void 0 ? void 0 : _g.maxRetryTimeMillis) !== null && _h !== void 0 ? _h : DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS,
158
+ onRetry: (error) => {
159
+ this.debugLogger(`Retrying failed API request "${description}"`, error);
160
+ },
134
161
  forever: false,
135
162
  };
136
163
  return asyncUtil_1.promiseWithTimeout(async_retry_1.default(async (bail) => {
@@ -152,7 +179,7 @@ class BasicApiClient {
152
179
  return {};
153
180
  }
154
181
  }
155
- }, retryOptions), DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS + 1000, 'Retryable API request');
182
+ }, retryOptions), retryOptions.maxRetryTime + retryOptions.maxTimeout, 'Retryable API request');
156
183
  }
157
184
  }
158
185
  exports.BasicApiClient = BasicApiClient;