usertold 1.9.1 → 1.9.2
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/package.json +1 -1
- package/usertold +103 -23
package/package.json
CHANGED
package/usertold
CHANGED
|
@@ -310,8 +310,8 @@ class HttpError extends CliError {
|
|
|
310
310
|
this.details = details;
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
|
-
async function requestJson(input) {
|
|
314
|
-
const response = await requestRaw(input);
|
|
313
|
+
async function requestJson(input, retryOptions) {
|
|
314
|
+
const response = await requestRaw(input, retryOptions);
|
|
315
315
|
if (!response.ok) {
|
|
316
316
|
throw new HttpError(response.status, extractErrorDetails(response));
|
|
317
317
|
}
|
|
@@ -371,7 +371,7 @@ async function requestJson(input) {
|
|
|
371
371
|
const arrayBuffer = await response.arrayBuffer();
|
|
372
372
|
return Buffer.from(arrayBuffer);
|
|
373
373
|
}
|
|
374
|
-
async function requestRaw(input) {
|
|
374
|
+
async function requestRaw(input, retryOptions) {
|
|
375
375
|
const method = input.method.toUpperCase();
|
|
376
376
|
const authMode = input.authMode ?? 'required';
|
|
377
377
|
const headers = {
|
|
@@ -395,21 +395,41 @@ async function requestRaw(input) {
|
|
|
395
395
|
}
|
|
396
396
|
const baseUrl = resolveBaseUrl(input.env);
|
|
397
397
|
const path = input.path.startsWith('/') ? input.path : `/${input.path}`;
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
398
|
+
const url = `${baseUrl}${path}`;
|
|
399
|
+
const retries = retryOptions?.retries ?? 0;
|
|
400
|
+
const initialDelayMs = retryOptions?.initialDelayMs ?? 500;
|
|
401
|
+
const maxDelayMs = retryOptions?.maxDelayMs ?? 4_000;
|
|
402
|
+
let delayMs = initialDelayMs;
|
|
403
|
+
let lastError;
|
|
404
|
+
for(let attempt = 0; attempt <= retries; attempt++){
|
|
405
|
+
try {
|
|
406
|
+
const response = await fetch(url, {
|
|
407
|
+
method,
|
|
408
|
+
headers,
|
|
409
|
+
body
|
|
410
|
+
});
|
|
411
|
+
const parsed = await toApiResponse(response);
|
|
412
|
+
if (attempt >= retries || !retryOptions?.shouldRetry?.({
|
|
413
|
+
attempt,
|
|
414
|
+
response: parsed
|
|
415
|
+
})) {
|
|
416
|
+
return parsed;
|
|
417
|
+
}
|
|
418
|
+
const retryAfterMs = parseRetryAfterMs(parsed.headers.get('Retry-After'));
|
|
419
|
+
await sleep$1(jitter$1(retryAfterMs ?? delayMs));
|
|
420
|
+
} catch (error) {
|
|
421
|
+
lastError = error;
|
|
422
|
+
if (attempt >= retries || !retryOptions?.shouldRetry?.({
|
|
423
|
+
attempt,
|
|
424
|
+
error
|
|
425
|
+
})) {
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
await sleep$1(jitter$1(delayMs));
|
|
429
|
+
}
|
|
430
|
+
delayMs = Math.min(maxDelayMs, delayMs * 2);
|
|
431
|
+
}
|
|
432
|
+
throw lastError ?? new Error('Request failed');
|
|
413
433
|
}
|
|
414
434
|
async function resolveToken(env, authMode) {
|
|
415
435
|
if (authMode === 'none') {
|
|
@@ -435,6 +455,9 @@ async function resolveToken(env, authMode) {
|
|
|
435
455
|
return config.token.accessToken;
|
|
436
456
|
}
|
|
437
457
|
function extractErrorDetails(response) {
|
|
458
|
+
if (isCloudflare1010Response(response)) {
|
|
459
|
+
return 'Cloudflare blocked this request (error 1010). Wait a few seconds and retry, or run pushes sequentially.';
|
|
460
|
+
}
|
|
438
461
|
if (response.json && typeof response.json === 'object' && response.json !== null) {
|
|
439
462
|
const body = response.json;
|
|
440
463
|
const maybeErrorCode = body.error_code;
|
|
@@ -472,6 +495,43 @@ function safeParseJson(text) {
|
|
|
472
495
|
return null;
|
|
473
496
|
}
|
|
474
497
|
}
|
|
498
|
+
async function toApiResponse(response) {
|
|
499
|
+
const text = await response.text();
|
|
500
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
501
|
+
const json = contentType.includes('application/json') && text.length > 0 ? safeParseJson(text) : null;
|
|
502
|
+
return {
|
|
503
|
+
status: response.status,
|
|
504
|
+
ok: response.ok,
|
|
505
|
+
headers: response.headers,
|
|
506
|
+
text,
|
|
507
|
+
json
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
function parseRetryAfterMs(value) {
|
|
511
|
+
if (!value) return null;
|
|
512
|
+
const seconds = Number(value);
|
|
513
|
+
if (!Number.isNaN(seconds) && seconds >= 0) {
|
|
514
|
+
return seconds * 1000;
|
|
515
|
+
}
|
|
516
|
+
const dateMs = Date.parse(value);
|
|
517
|
+
if (Number.isNaN(dateMs)) {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
return Math.max(0, dateMs - Date.now());
|
|
521
|
+
}
|
|
522
|
+
function jitter$1(ms) {
|
|
523
|
+
return ms * (0.7 + Math.random() * 0.6);
|
|
524
|
+
}
|
|
525
|
+
function sleep$1(ms) {
|
|
526
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
527
|
+
}
|
|
528
|
+
function isCloudflare1010Response(response) {
|
|
529
|
+
const text = response.text.toLowerCase();
|
|
530
|
+
if (text.includes('error code 1010') || text.includes('error code: 1010')) {
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
return text.includes('access denied') && text.includes("browser's signature");
|
|
534
|
+
}
|
|
475
535
|
|
|
476
536
|
/**
|
|
477
537
|
* Returns true when output should be JSON:
|
|
@@ -9280,7 +9340,8 @@ function requestProjectContract(options) {
|
|
|
9280
9340
|
body: options.body,
|
|
9281
9341
|
authMode: options.authMode,
|
|
9282
9342
|
projectKey: options.projectKey,
|
|
9283
|
-
headers: options.headers
|
|
9343
|
+
headers: options.headers,
|
|
9344
|
+
retryOptions: options.retryOptions
|
|
9284
9345
|
};
|
|
9285
9346
|
return doRequestContract({
|
|
9286
9347
|
env: options.env
|
|
@@ -9347,7 +9408,7 @@ async function doRequestContract(defaults, key, options) {
|
|
|
9347
9408
|
authMode: options.authMode ?? defaults.authMode,
|
|
9348
9409
|
projectKey: options.projectKey ?? defaults.projectKey,
|
|
9349
9410
|
headers: mergeHeaders(defaults.headers, options.headers)
|
|
9350
|
-
});
|
|
9411
|
+
}, options.retryOptions);
|
|
9351
9412
|
}
|
|
9352
9413
|
function mergeHeaders(defaults, overrides) {
|
|
9353
9414
|
if (!defaults && !overrides) {
|
|
@@ -11050,6 +11111,12 @@ const FLAGS$a = {
|
|
|
11050
11111
|
],
|
|
11051
11112
|
'push-status': []
|
|
11052
11113
|
};
|
|
11114
|
+
const TASK_PUSH_RETRY_OPTIONS = {
|
|
11115
|
+
retries: 4,
|
|
11116
|
+
initialDelayMs: 500,
|
|
11117
|
+
maxDelayMs: 4_000,
|
|
11118
|
+
shouldRetry: ({ response, error })=>isRetryableTaskPushFailure(response, error)
|
|
11119
|
+
};
|
|
11053
11120
|
async function handleTaskCommand(subcommand, parsed) {
|
|
11054
11121
|
if (!subcommand || hasHelpFlag(parsed) || subcommand === 'help' || subcommand === '--help' || subcommand === '-h') {
|
|
11055
11122
|
printTaskHelp();
|
|
@@ -11279,7 +11346,8 @@ async function handleTaskCommand(subcommand, parsed) {
|
|
|
11279
11346
|
sourceLabel: '<projectRef>',
|
|
11280
11347
|
pathParams: {
|
|
11281
11348
|
taskId: taskId
|
|
11282
|
-
}
|
|
11349
|
+
},
|
|
11350
|
+
retryOptions: TASK_PUSH_RETRY_OPTIONS
|
|
11283
11351
|
});
|
|
11284
11352
|
printOutput(data, parsed);
|
|
11285
11353
|
return;
|
|
@@ -11354,6 +11422,18 @@ Examples:
|
|
|
11354
11422
|
function printTaskHelp() {
|
|
11355
11423
|
console.log(TASK_HELP);
|
|
11356
11424
|
}
|
|
11425
|
+
function isRetryableTaskPushFailure(response, error) {
|
|
11426
|
+
if (response) {
|
|
11427
|
+
if (response.status === 429) {
|
|
11428
|
+
return true;
|
|
11429
|
+
}
|
|
11430
|
+
if (response.status >= 500 && response.status <= 504) {
|
|
11431
|
+
return true;
|
|
11432
|
+
}
|
|
11433
|
+
return response.status === 403 && isCloudflare1010Response(response);
|
|
11434
|
+
}
|
|
11435
|
+
return error instanceof Error;
|
|
11436
|
+
}
|
|
11357
11437
|
|
|
11358
11438
|
const FLAGS$9 = {
|
|
11359
11439
|
list: [],
|
|
@@ -14633,7 +14713,7 @@ function printExtractHelp() {
|
|
|
14633
14713
|
console.log(EXTRACT_HELP);
|
|
14634
14714
|
}
|
|
14635
14715
|
|
|
14636
|
-
const CLI_VERSION$1 = '1.9.
|
|
14716
|
+
const CLI_VERSION$1 = '1.9.2';
|
|
14637
14717
|
const GLOBAL_FLAGS = [
|
|
14638
14718
|
'env',
|
|
14639
14719
|
'json',
|
|
@@ -14929,7 +15009,7 @@ function printCompletionsHelp() {
|
|
|
14929
15009
|
console.log(COMPLETIONS_HELP);
|
|
14930
15010
|
}
|
|
14931
15011
|
|
|
14932
|
-
const CLI_VERSION = '1.9.
|
|
15012
|
+
const CLI_VERSION = '1.9.2';
|
|
14933
15013
|
function detectJsonMode() {
|
|
14934
15014
|
const argv = process$2.argv.slice(2);
|
|
14935
15015
|
if (argv.includes('--json')) return true;
|