@mablhq/mabl-cli 1.16.5 → 1.16.11
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/api/basicApiClient.js +52 -28
- package/api/mablApiClient.js +1 -1
- package/browserLauncher/pageEvent.js +1 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightPage.js +6 -0
- package/browserLauncher/puppeteerBrowserLauncher/puppeteerPage.js +6 -0
- package/domUtil/index.js +1 -1
- package/execution/index.js +1 -1
- package/package.json +1 -1
package/api/basicApiClient.js
CHANGED
|
@@ -37,6 +37,14 @@ const DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS = DEFAULT_RETRYABLE_REQUEST_TIME
|
|
|
37
37
|
const DEFAULT_NONRETRYABLE_REQUEST_TIMEOUT_MILLISECONDS = DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS;
|
|
38
38
|
const DEFAULT_MIN_RETRY_INTERVAL_MILLISECONDS = 1000;
|
|
39
39
|
const DEFAULT_MAX_RETRY_INTERVAL_MILLISECONDS = 10000;
|
|
40
|
+
const RETRYABLE_NODEJS_ERRORS = [
|
|
41
|
+
'EAI_AGAIN',
|
|
42
|
+
'ECONNRESET',
|
|
43
|
+
'ENOTFOUND',
|
|
44
|
+
'ENETUNREACH',
|
|
45
|
+
'ETIMEOUT',
|
|
46
|
+
'ECONNABORTED',
|
|
47
|
+
];
|
|
40
48
|
var AuthType;
|
|
41
49
|
(function (AuthType) {
|
|
42
50
|
AuthType[AuthType["Bearer"] = 0] = "Bearer";
|
|
@@ -44,12 +52,12 @@ var AuthType;
|
|
|
44
52
|
})(AuthType = exports.AuthType || (exports.AuthType = {}));
|
|
45
53
|
class BasicApiClient {
|
|
46
54
|
constructor(options) {
|
|
47
|
-
var _a, _b;
|
|
55
|
+
var _a, _b, _c, _d;
|
|
48
56
|
const config = httpUtil_1.axiosProxyConfig({
|
|
49
57
|
sslVerify: options.sslVerify,
|
|
50
58
|
proxyHost: options.proxyUrl,
|
|
51
59
|
});
|
|
52
|
-
config.timeout = (_a = options.requestTimeoutMillis) !== null && _a !== void 0 ? _a : DEFAULT_RETRYABLE_REQUEST_TIMEOUT_MILLISECONDS;
|
|
60
|
+
config.timeout = (_c = (_a = options.requestTimeoutMillis) !== null && _a !== void 0 ? _a : (_b = options.retryConfig) === null || _b === void 0 ? void 0 : _b.requestTimeoutMillis) !== null && _c !== void 0 ? _c : DEFAULT_RETRYABLE_REQUEST_TIMEOUT_MILLISECONDS;
|
|
53
61
|
switch (options.authType) {
|
|
54
62
|
case AuthType.ApiKey:
|
|
55
63
|
config.auth = {
|
|
@@ -77,7 +85,7 @@ class BasicApiClient {
|
|
|
77
85
|
this.httpRequestConfig = config;
|
|
78
86
|
this.httpClient = axios_1.default.create(config);
|
|
79
87
|
this.retryConfig = options.retryConfig;
|
|
80
|
-
this.debugLogger = (
|
|
88
|
+
this.debugLogger = (_d = options.debugLogger) !== null && _d !== void 0 ? _d : logUtils_1.logInternal;
|
|
81
89
|
}
|
|
82
90
|
getNonRetryableRequestConfig(override) {
|
|
83
91
|
const overrideWithTimeout = { ...(override !== null && override !== void 0 ? override : {}) };
|
|
@@ -87,20 +95,26 @@ class BasicApiClient {
|
|
|
87
95
|
}
|
|
88
96
|
return { ...this.httpRequestConfig, ...overrideWithTimeout };
|
|
89
97
|
}
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
getRetryableRequestConfig(retryConfig) {
|
|
99
|
+
var _a;
|
|
100
|
+
return this.getNonRetryableRequestConfig({
|
|
101
|
+
timeout: (_a = retryConfig === null || retryConfig === void 0 ? void 0 : retryConfig.requestTimeoutMillis) !== null && _a !== void 0 ? _a : this.httpRequestConfig.timeout,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
makeGetRequest(path, retryConfig) {
|
|
105
|
+
return this.retryWrappedRequest(`makeGetRequest('${path}')`, () => this.getRequest(path, this.getRetryableRequestConfig(retryConfig)), retryConfig);
|
|
92
106
|
}
|
|
93
|
-
async getRequest(path) {
|
|
94
|
-
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
|
|
107
|
+
async getRequest(path, config) {
|
|
108
|
+
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path, config));
|
|
95
109
|
BasicApiClient.checkResponseStatusCode(response);
|
|
96
110
|
return response.data;
|
|
97
111
|
}
|
|
98
|
-
makeGetRequestWithETag(path) {
|
|
99
|
-
return this.retryWrappedRequest(`makeGetRequestWithETag('${path}')`, () => this.getRequestWithETag(path));
|
|
112
|
+
makeGetRequestWithETag(path, retryConfig) {
|
|
113
|
+
return this.retryWrappedRequest(`makeGetRequestWithETag('${path}')`, () => this.getRequestWithETag(path, this.getRetryableRequestConfig(retryConfig)), retryConfig);
|
|
100
114
|
}
|
|
101
|
-
async getRequestWithETag(path) {
|
|
115
|
+
async getRequestWithETag(path, config) {
|
|
102
116
|
var _a;
|
|
103
|
-
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
|
|
117
|
+
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path, config));
|
|
104
118
|
BasicApiClient.checkResponseStatusCode(response);
|
|
105
119
|
const headers = response.headers;
|
|
106
120
|
const result = response.data;
|
|
@@ -120,11 +134,11 @@ class BasicApiClient {
|
|
|
120
134
|
BasicApiClient.checkResponseStatusCode(response);
|
|
121
135
|
return response.data;
|
|
122
136
|
}
|
|
123
|
-
makeDeleteRequest(path) {
|
|
124
|
-
return this.retryWrappedRequest(`makeDeleteRequest('${path}')`, () => this.deleteRequest(path));
|
|
137
|
+
makeDeleteRequest(path, retryConfig) {
|
|
138
|
+
return this.retryWrappedRequest(`makeDeleteRequest('${path}')`, () => this.deleteRequest(path, this.getRetryableRequestConfig(retryConfig)), retryConfig);
|
|
125
139
|
}
|
|
126
|
-
async deleteRequest(path) {
|
|
127
|
-
const response = await this.debugRequest('DELETE', path, () => this.deleteRequest(path));
|
|
140
|
+
async deleteRequest(path, config) {
|
|
141
|
+
const response = await this.debugRequest('DELETE', path, () => this.deleteRequest(path, config));
|
|
128
142
|
BasicApiClient.checkResponseStatusCode(response);
|
|
129
143
|
return response.data;
|
|
130
144
|
}
|
|
@@ -158,38 +172,48 @@ class BasicApiClient {
|
|
|
158
172
|
throw new ApiError_1.ApiError(`[${statusCode} - ${response.statusText}]`, statusCode);
|
|
159
173
|
}
|
|
160
174
|
}
|
|
161
|
-
retryWrappedRequest(description, requestFunc) {
|
|
162
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
175
|
+
retryWrappedRequest(description, requestFunc, retryConfigOverride) {
|
|
176
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
163
177
|
const retryOptions = {
|
|
164
|
-
retries: (
|
|
165
|
-
minTimeout: (_d = (
|
|
166
|
-
maxTimeout: (
|
|
167
|
-
maxRetryTime: (
|
|
178
|
+
retries: (_c = (_a = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.retryCount) !== null && _a !== void 0 ? _a : (_b = this.retryConfig) === null || _b === void 0 ? void 0 : _b.retryCount) !== null && _c !== void 0 ? _c : DEFAULT_RETRIES,
|
|
179
|
+
minTimeout: (_f = (_d = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.minRetryIntervalMillis) !== null && _d !== void 0 ? _d : (_e = this.retryConfig) === null || _e === void 0 ? void 0 : _e.minRetryIntervalMillis) !== null && _f !== void 0 ? _f : DEFAULT_MIN_RETRY_INTERVAL_MILLISECONDS,
|
|
180
|
+
maxTimeout: (_j = (_g = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.maxRetryIntervalMillis) !== null && _g !== void 0 ? _g : (_h = this.retryConfig) === null || _h === void 0 ? void 0 : _h.maxRetryIntervalMillis) !== null && _j !== void 0 ? _j : DEFAULT_MAX_RETRY_INTERVAL_MILLISECONDS,
|
|
181
|
+
maxRetryTime: (_m = (_k = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.maxRetryTimeMillis) !== null && _k !== void 0 ? _k : (_l = this.retryConfig) === null || _l === void 0 ? void 0 : _l.maxRetryTimeMillis) !== null && _m !== void 0 ? _m : DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS,
|
|
168
182
|
onRetry: (error) => {
|
|
169
183
|
this.debugLogger(`Retrying failed API request "${description}"`, error);
|
|
170
184
|
},
|
|
171
185
|
forever: false,
|
|
172
186
|
};
|
|
173
187
|
return asyncUtil_1.promiseWithTimeout(async_retry_1.default(async (bail) => {
|
|
174
|
-
var _a, _b;
|
|
175
188
|
try {
|
|
176
189
|
return await requestFunc();
|
|
177
190
|
}
|
|
178
191
|
catch (error) {
|
|
179
|
-
|
|
180
|
-
const statusCode = (_a = axiosError.code) !== null && _a !== void 0 ? _a : (_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.status;
|
|
181
|
-
if (statusCode === 429 ||
|
|
182
|
-
statusCode === 502 ||
|
|
183
|
-
statusCode === 503 ||
|
|
184
|
-
statusCode === 504) {
|
|
192
|
+
if (axios_1.default.isAxiosError(error) && BasicApiClient.isRetryable(error)) {
|
|
185
193
|
throw error;
|
|
186
194
|
}
|
|
187
195
|
else {
|
|
196
|
+
let code;
|
|
197
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
198
|
+
code = error.code;
|
|
199
|
+
}
|
|
200
|
+
this.debugLogger(`Non-retryable error on API client: ${code} ${description} ${error}`);
|
|
188
201
|
bail(error);
|
|
189
202
|
return {};
|
|
190
203
|
}
|
|
191
204
|
}
|
|
192
205
|
}, retryOptions), retryOptions.maxRetryTime + retryOptions.maxTimeout, 'Retryable API request');
|
|
193
206
|
}
|
|
207
|
+
static isRetryable(axiosError) {
|
|
208
|
+
if (axiosError.response) {
|
|
209
|
+
const statusCode = axiosError.response.status;
|
|
210
|
+
return (statusCode === 429 ||
|
|
211
|
+
statusCode === 502 ||
|
|
212
|
+
statusCode === 503 ||
|
|
213
|
+
statusCode === 504);
|
|
214
|
+
}
|
|
215
|
+
return (axiosError.code !== undefined &&
|
|
216
|
+
RETRYABLE_NODEJS_ERRORS.includes(axiosError.code));
|
|
217
|
+
}
|
|
194
218
|
}
|
|
195
219
|
exports.BasicApiClient = BasicApiClient;
|
package/api/mablApiClient.js
CHANGED
|
@@ -227,7 +227,7 @@ class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
|
227
227
|
}
|
|
228
228
|
async getDeploymentResults(deploymentEventId) {
|
|
229
229
|
try {
|
|
230
|
-
return await this.makeGetRequest(`${env_1.BASE_API_URL}/execution/result/event/${deploymentEventId}
|
|
230
|
+
return await this.makeGetRequest(`${env_1.BASE_API_URL}/execution/result/event/${deploymentEventId}`, { requestTimeoutMillis: 600000, maxRetryTimeMillis: 900000 });
|
|
231
231
|
}
|
|
232
232
|
catch (error) {
|
|
233
233
|
throw toApiError(`Failed to get deployment results`, error);
|
|
@@ -13,4 +13,5 @@ var PageEvent;
|
|
|
13
13
|
PageEvent["Response"] = "response";
|
|
14
14
|
PageEvent["TracingBufferUsage"] = "tracingbufferusage";
|
|
15
15
|
PageEvent["TracingComplete"] = "tracingcomplete";
|
|
16
|
+
PageEvent["TracingDataCollected"] = "TracingDataCollected";
|
|
16
17
|
})(PageEvent = exports.PageEvent || (exports.PageEvent = {}));
|
|
@@ -130,6 +130,12 @@ class PlaywrightPage extends events_1.default {
|
|
|
130
130
|
this.emit(browserLauncher_1.PageEvent.TracingBufferUsage, tracing);
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
|
+
if (event === browserLauncher_1.PageEvent.TracingDataCollected &&
|
|
134
|
+
!this.listenerCount(event)) {
|
|
135
|
+
this.getCdpSession().on('Tracing.dataCollected', (data) => {
|
|
136
|
+
this.emit(browserLauncher_1.PageEvent.TracingDataCollected, data);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
133
139
|
if (event === browserLauncher_1.PageEvent.TracingComplete && !this.listenerCount(event)) {
|
|
134
140
|
this.getCdpSession().on('Tracing.tracingComplete', (tracingComplete) => {
|
|
135
141
|
this.emit(browserLauncher_1.PageEvent.TracingComplete, tracingComplete);
|
|
@@ -245,6 +245,12 @@ class PuppeteerPage extends events_1.default {
|
|
|
245
245
|
this.emit(browserLauncher_1.PageEvent.TracingComplete, tracingComplete);
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
|
+
if (event === browserLauncher_1.PageEvent.TracingDataCollected &&
|
|
249
|
+
!this.listenerCount(event)) {
|
|
250
|
+
this.getCdpClient().on('Tracing.dataCollected', (data) => {
|
|
251
|
+
this.emit(browserLauncher_1.PageEvent.TracingComplete, data);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
248
254
|
}
|
|
249
255
|
evaluateHandleInSecondaryWorld(code, ...args) {
|
|
250
256
|
return this.mainFrame().evaluateHandleInSecondaryWorld(code, ...args);
|