diff --git a/src/cli-options.ts b/src/cli-options.ts index 9992bcd8..2733c2e4 100644 --- a/src/cli-options.ts +++ b/src/cli-options.ts @@ -306,6 +306,13 @@ As a comparison: without using the --peer option, ncu will suggest the latest ve arg: 'ms', description: 'Global timeout in milliseconds. (default: no global timeout and 30 seconds per npm-registry-fetch).', }, + { + long: 'retry', + arg: 'rt', + description: 'Global request retries.', + parse: s => parseInt(s, 10), + default: 2, + }, { long: 'upgrade', short: 'u', diff --git a/src/lib/queryVersions.ts b/src/lib/queryVersions.ts index 6ca50611..d605a288 100644 --- a/src/lib/queryVersions.ts +++ b/src/lib/queryVersions.ts @@ -73,6 +73,7 @@ async function queryVersions(packageMap: Index, options: Options = ...options, // upgrade prereleases to newer prereleases by default pre: options.pre != null ? options.pre : isPre(version), + retry: options.retry ?? 2, }) versionNew = npmAlias && versionNew ? createNpmAlias(name, versionNew) : versionNew } diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index f6b35c7c..d11abcb5 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -135,17 +135,29 @@ export async function packageAuthorChanged(packageName: string, currentVersion: * @param currentVersion * @returns Promised result */ -export async function viewMany(packageName: string, fields: string[], currentVersion: Version, { registry, timeout }: { registry?: string, timeout?: number } = {}) { +export async function viewMany(packageName: string, fields: string[], currentVersion: Version, { registry, timeout, retry }: { registry?: string, timeout?: number, retry?: number } = {}, retryed = 0) { if (currentVersion && (!semver.validRange(currentVersion) || versionUtil.isWildCard(currentVersion))) { return Promise.resolve({} as Packument) } - const result = await pacote.packument(packageName, { - ...npmConfig, - fullMetadata: fields.includes('time'), - ...registry ? { registry } : null, - timeout, - }) + let result: any + try { + result = await pacote.packument(packageName, { + ...npmConfig, + fullMetadata: fields.includes('time'), + ...registry ? { registry } : null, + timeout, + }) + } + catch (err: any) { + if (retry && ++retryed <= retry) { + console.error(`\nFetchError: Request ${packageName} info failed[${retryed} of ${retry}]: \n${err.message}.`) + const packument: Packument = await viewMany(packageName, fields, currentVersion, { registry, timeout, retry }, retryed) + return packument + } + + throw err + } return fields.reduce((accum, field) => ({ ...accum, [field]: field.startsWith('dist-tags.') && result.versions ? @@ -305,6 +317,7 @@ export const latest: GetVersion = async (packageName, currentVersion, options = const latest = await viewOne(packageName, 'dist-tags.latest', currentVersion, { registry: options.registry, timeout: options.timeout, + retry: options.retry, }) as unknown as Packument // known type based on dist-tags.latest // latest should not be deprecated diff --git a/src/package-managers/yarn.ts b/src/package-managers/yarn.ts index 6b15b68e..9863b8c2 100644 --- a/src/package-managers/yarn.ts +++ b/src/package-managers/yarn.ts @@ -174,6 +174,7 @@ export const latest: GetVersion = async (packageName: string, currentVersion: Ve const latest = await viewOne(packageName, 'dist-tags.latest', currentVersion, { registry: options.registry, timeout: options.timeout, + retry: options.retry, }) as unknown as Packument // known type based on dist-tags.latest // latest should not be deprecated diff --git a/src/types.ts b/src/types.ts index 3107bdc6..e90ba20a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -288,6 +288,11 @@ export interface RunOptions { */ timeout?: number, + /** + * Global request retries. (default: 3). + */ + retry?: number, + /** * Overwrite package file with upgraded versions instead of just outputting to console. */