mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 07:38:12 -05:00
6
.changeset/chilly-hounds-cross.md
Normal file
6
.changeset/chilly-hounds-cross.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/fetch": major
|
||||
"fetch-from-npm-registry": minor
|
||||
---
|
||||
|
||||
Print a warning when request fails and a retry will happen. Breaking changes in the programmatic API of `@pnpm/fetch`.
|
||||
6
.changeset/poor-needles-share.md
Normal file
6
.changeset/poor-needles-share.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/core-loggers": minor
|
||||
"@pnpm/default-reporter": minor
|
||||
---
|
||||
|
||||
New reporter added for request retries.
|
||||
5
.changeset/spicy-games-bake.md
Normal file
5
.changeset/spicy-games-bake.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/tarball-fetcher": minor
|
||||
---
|
||||
|
||||
Print a warning when tarball request fails.
|
||||
@@ -9,7 +9,7 @@
|
||||
"test-branch": "pnpm run lint && git remote set-branches --add origin master && git fetch && pnpm run compile && run-p -r verdaccio test-pkgs-branch --workspace-concurrency=2",
|
||||
"test-pkgs-branch": "cross-env PNPM_REGISTRY_MOCK_UPLINK=http://localhost:7348 pnpm run _test --no-sort --filter=...[origin/master]",
|
||||
"verdaccio": "verdaccio --config ./verdaccio.yaml --listen 7348",
|
||||
"compile": "pnpm run --filter @pnpm/fetch compile && pnpm run --filter pnpm compile && pnpm run update-manifests",
|
||||
"compile": "pnpm run --filter pnpm compile && pnpm run update-manifests",
|
||||
"watch": "pnpm run --filter @pnpm/fetch compile && pnpm run --filter pnpm compile -- --watch",
|
||||
"coveralls": "lcov-result-merger './packages/*/coverage/lcov.info' | coveralls",
|
||||
"update-manifests": "ts-node utils/updater/src/index.ts"
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
{
|
||||
"path": "../error"
|
||||
},
|
||||
{
|
||||
"path": "../fetch"
|
||||
},
|
||||
{
|
||||
"path": "../lockfile-types"
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@ export * from './linkLogger'
|
||||
export * from './packageManifestLogger'
|
||||
export * from './progressLogger'
|
||||
export * from './registryLogger'
|
||||
export * from './requestRetryLogger'
|
||||
export * from './removalLogger'
|
||||
export * from './rootLogger'
|
||||
export * from './scopeLogger'
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
PackageManifestLog,
|
||||
ProgressLog,
|
||||
RegistryLog,
|
||||
RequestRetryLog,
|
||||
RootLog,
|
||||
ScopeLog,
|
||||
SkippedOptionalDependencyLog,
|
||||
@@ -19,7 +20,8 @@ import {
|
||||
SummaryLog,
|
||||
} from './all'
|
||||
|
||||
export type Log = DeprecationLog
|
||||
export type Log =
|
||||
| DeprecationLog
|
||||
| FetchingProgressLog
|
||||
| HookLog
|
||||
| ImportingLog
|
||||
@@ -29,6 +31,7 @@ export type Log = DeprecationLog
|
||||
| PackageManifestLog
|
||||
| ProgressLog
|
||||
| RegistryLog
|
||||
| RequestRetryLog
|
||||
| RootLog
|
||||
| ScopeLog
|
||||
| SkippedOptionalDependencyLog
|
||||
|
||||
16
packages/core-loggers/src/requestRetryLogger.ts
Normal file
16
packages/core-loggers/src/requestRetryLogger.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import baseLogger, {
|
||||
LogBase,
|
||||
} from '@pnpm/logger'
|
||||
|
||||
export const requestRetryLogger = baseLogger<RequestRetryMessage>('request-retry')
|
||||
|
||||
export interface RequestRetryMessage {
|
||||
attempt: number,
|
||||
error: Error,
|
||||
maxRetries: number,
|
||||
method: string,
|
||||
timeout: number,
|
||||
url: string,
|
||||
}
|
||||
|
||||
export type RequestRetryLog = { name: 'pnpm:request-retry' } & LogBase & RequestRetryMessage
|
||||
@@ -41,6 +41,7 @@
|
||||
"most": "^1.8.1",
|
||||
"normalize-path": "3.0.0",
|
||||
"pretty-bytes": "5.3.0",
|
||||
"pretty-ms": "^7.0.0",
|
||||
"pretty-time": "1.1.0",
|
||||
"ramda": "0.27.0",
|
||||
"right-pad": "1.0.1",
|
||||
|
||||
@@ -93,6 +93,7 @@ export function toOutput$ (
|
||||
const hookPushStream = new PushStream()
|
||||
const skippedOptionalDependencyPushStream = new PushStream()
|
||||
const scopePushStream = new PushStream()
|
||||
const requestRetryPushStream = new PushStream()
|
||||
setTimeout(() => { // setTimeout is a workaround for a strange bug in most https://github.com/cujojs/most/issues/491
|
||||
opts.streamParser['on']('data', (log: logs.Log) => {
|
||||
switch (log.name) {
|
||||
@@ -141,6 +142,9 @@ export function toOutput$ (
|
||||
case 'pnpm:scope':
|
||||
scopePushStream.next(log)
|
||||
break
|
||||
case 'pnpm:request-retry':
|
||||
requestRetryPushStream.next(log)
|
||||
break
|
||||
case 'pnpm' as any: // tslint:disable-line
|
||||
case 'pnpm:global' as any: // tslint:disable-line
|
||||
case 'pnpm:store' as any: // tslint:disable-line
|
||||
@@ -161,6 +165,7 @@ export function toOutput$ (
|
||||
packageManifest: most.from<logs.PackageManifestLog>(packageManifestPushStream.observable),
|
||||
progress: most.from<logs.ProgressLog>(progressPushStream.observable),
|
||||
registry: most.from<logs.RegistryLog>(registryPushStream.observable),
|
||||
requestRetry: most.from<logs.RequestRetryLog>(requestRetryPushStream.observable),
|
||||
root: most.from<logs.RootLog>(rootPushStream.observable),
|
||||
scope: most.from<logs.ScopeLog>(scopePushStream.observable),
|
||||
skippedOptionalDependency: most.from<logs.SkippedOptionalDependencyLog>(skippedOptionalDependencyPushStream.observable),
|
||||
|
||||
@@ -9,6 +9,7 @@ import reportInstallChecks from './reportInstallChecks'
|
||||
import reportLifecycleScripts from './reportLifecycleScripts'
|
||||
import reportMisc from './reportMisc'
|
||||
import reportProgress from './reportProgress'
|
||||
import reportRequestRetry from './reportRequestRetry'
|
||||
import reportScope from './reportScope'
|
||||
import reportSkippedOptionalDependencies from './reportSkippedOptionalDependencies'
|
||||
import reportStats from './reportStats'
|
||||
@@ -27,6 +28,7 @@ export default function (
|
||||
registry: most.Stream<logs.RegistryLog>,
|
||||
root: most.Stream<logs.RootLog>,
|
||||
packageManifest: most.Stream<logs.PackageManifestLog>,
|
||||
requestRetry: most.Stream<logs.RequestRetryLog>,
|
||||
link: most.Stream<logs.LinkLog>,
|
||||
other: most.Stream<logs.Log>,
|
||||
hook: most.Stream<logs.HookLog>,
|
||||
@@ -73,6 +75,7 @@ export default function (
|
||||
width,
|
||||
}),
|
||||
reportInstallChecks(log$.installCheck, { cwd }),
|
||||
reportRequestRetry(log$.requestRetry),
|
||||
reportScope(log$.scope, { isRecursive: opts.isRecursive, cmd: opts.cmd }),
|
||||
reportSkippedOptionalDependencies(log$.skippedOptionalDependency, { cwd }),
|
||||
reportHooks(log$.hook, { cwd, isRecursive: opts.isRecursive }),
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { RequestRetryLog } from '@pnpm/core-loggers'
|
||||
import { oneLine } from 'common-tags'
|
||||
import most = require('most')
|
||||
import prettyMilliseconds = require('pretty-ms')
|
||||
import formatWarn from './utils/formatWarn'
|
||||
|
||||
export default (
|
||||
requestRetry$: most.Stream<RequestRetryLog>
|
||||
) => {
|
||||
return requestRetry$
|
||||
.map((log) => {
|
||||
const retriesLeft = log.maxRetries - log.attempt + 1
|
||||
const errorCode = log.error['httpStatusCode'] || log.error['status'] || log.error['errno'] || log.error['code']
|
||||
const msg = oneLine`${log.method} ${log.url} error (${errorCode}).
|
||||
Will retry in ${prettyMilliseconds(log.timeout, { verbose: true })}.
|
||||
${retriesLeft} retries left.`
|
||||
return most.of({ msg: formatWarn(msg) })
|
||||
})
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import test = require('tape')
|
||||
import './reportingErrors'
|
||||
import './reportingLifecycleScripts'
|
||||
import './reportingProgress'
|
||||
import './reportingRequestRetry'
|
||||
import './reportingScope'
|
||||
|
||||
const WARN = chalk.bgYellow.black('\u2009WARN\u2009')
|
||||
|
||||
37
packages/default-reporter/test/reportingRequestRetry.ts
Normal file
37
packages/default-reporter/test/reportingRequestRetry.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { requestRetryLogger } from '@pnpm/core-loggers'
|
||||
import { toOutput$ } from '@pnpm/default-reporter'
|
||||
import {
|
||||
createStreamParser,
|
||||
} from '@pnpm/logger'
|
||||
import chalk = require('chalk')
|
||||
import test = require('tape')
|
||||
|
||||
const WARN = chalk.bgYellow.black('\u2009WARN\u2009')
|
||||
|
||||
test('print warning about request retry', (t) => {
|
||||
const output$ = toOutput$({
|
||||
context: {
|
||||
argv: ['install'],
|
||||
},
|
||||
streamParser: createStreamParser(),
|
||||
})
|
||||
|
||||
requestRetryLogger.debug({
|
||||
attempt: 2,
|
||||
error: new Error(),
|
||||
maxRetries: 5,
|
||||
method: 'GET',
|
||||
timeout: 12500,
|
||||
url: 'https://foo.bar/qar',
|
||||
})
|
||||
|
||||
t.plan(1)
|
||||
|
||||
output$.take(1).subscribe({
|
||||
complete: () => t.end(),
|
||||
error: t.end,
|
||||
next: output => {
|
||||
t.equal(output, `${WARN} GET https://foo.bar/qar error (undefined). Will retry in 12.5 seconds. 4 retries left.`)
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -29,6 +29,9 @@
|
||||
"url": "https://github.com/pnpm/pnpm/issues"
|
||||
},
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/master/packages/fetch-from-npm-registry#readme",
|
||||
"peerDependencies": {
|
||||
"@pnpm/logger": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pnpm/fetch": "workspace:1.0.3",
|
||||
"@pnpm/npm-registry-agent": "workspace:2.0.3"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import fetch, { Response } from '@pnpm/fetch'
|
||||
import fetch, { isRedirect, Response } from '@pnpm/fetch'
|
||||
import npmRegistryAgent from '@pnpm/npm-registry-agent'
|
||||
import { URL } from 'url'
|
||||
|
||||
@@ -62,7 +62,7 @@ export default function (
|
||||
redirect: 'manual',
|
||||
retry: defaultOpts.retry,
|
||||
})
|
||||
if (!fetch.isRedirect(response.status) || redirects >= MAX_FOLLOWED_REDIRECTS) {
|
||||
if (!isRedirect(response.status) || redirects >= MAX_FOLLOWED_REDIRECTS) {
|
||||
return response
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
"../../typings/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../fetch"
|
||||
},
|
||||
{
|
||||
"path": "../npm-registry-agent"
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"lint": "tslint -c ../../tslint.json src/**/*.ts test/**/*.ts",
|
||||
"test": "pnpm run compile",
|
||||
"prepublishOnly": "pnpm run compile",
|
||||
"compile": "rimraf lib && tsc && cpy src/**/*.d.ts lib"
|
||||
"compile": "rimraf lib tsconfig.tsbuildinfo && tsc --build"
|
||||
},
|
||||
"repository": "https://github.com/pnpm/pnpm/blob/master/packages/fetch",
|
||||
"keywords": [
|
||||
@@ -27,13 +27,18 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/pnpm/pnpm/issues"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@pnpm/logger": "^3.1.0"
|
||||
},
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/master/packages/fetch#readme",
|
||||
"dependencies": {
|
||||
"@zeit/fetch-retry": "5.0.0",
|
||||
"@pnpm/core-loggers": "workspace:^4.0.2",
|
||||
"@zkochan/retry": "^0.2.0",
|
||||
"node-fetch": "2.6.0",
|
||||
"node-fetch-unix": "2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pnpm/logger": "^3.2.2",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"cpy-cli": "^3.1.1"
|
||||
},
|
||||
|
||||
48
packages/fetch/src/index.d.ts
vendored
48
packages/fetch/src/index.d.ts
vendored
@@ -1,48 +0,0 @@
|
||||
import { Request, RequestInit as NodeRequestInit, Response } from 'node-fetch'
|
||||
export {
|
||||
FetchError,
|
||||
Headers,
|
||||
HeadersInit,
|
||||
RequestContext,
|
||||
RequestMode,
|
||||
RequestRedirect,
|
||||
RequestCredentials,
|
||||
RequestCache,
|
||||
ResponseType,
|
||||
ResponseInit,
|
||||
} from 'node-fetch'
|
||||
|
||||
export {
|
||||
Request,
|
||||
Response,
|
||||
}
|
||||
|
||||
interface URLLike {
|
||||
href: string
|
||||
}
|
||||
|
||||
export interface RetryOpts {
|
||||
factor?: number
|
||||
maxTimeout?: number
|
||||
minTimeout?: number
|
||||
onRetry? (error: unknown): void
|
||||
retries?: number
|
||||
}
|
||||
|
||||
export interface RequestInit extends NodeRequestInit {
|
||||
retry?: RetryOpts
|
||||
onRetry? (error: unknown, opts: RequestInit): void
|
||||
}
|
||||
|
||||
export type RequestInfo = string | URLLike | Request
|
||||
|
||||
declare function fetch (
|
||||
url: RequestInfo,
|
||||
init?: RequestInit
|
||||
): Promise<Response>
|
||||
|
||||
declare namespace fetch {
|
||||
function isRedirect (code: number): boolean
|
||||
}
|
||||
|
||||
export default fetch
|
||||
@@ -1,9 +0,0 @@
|
||||
const createFetchRetry = require('@zeit/fetch-retry')
|
||||
const nodeFetch = require('node-fetch-unix')
|
||||
|
||||
export default createFetchRetry(nodeFetch)
|
||||
|
||||
export const FetchError = nodeFetch.FetchError
|
||||
export const Headers = nodeFetch.Headers
|
||||
export const Request = nodeFetch.Request
|
||||
export const Response = nodeFetch.Response
|
||||
102
packages/fetch/src/index.ts
Normal file
102
packages/fetch/src/index.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { requestRetryLogger } from '@pnpm/core-loggers'
|
||||
import * as retry from '@zkochan/retry'
|
||||
import { Request, RequestInit as NodeRequestInit, Response } from 'node-fetch'
|
||||
import fetch = require('node-fetch-unix')
|
||||
|
||||
// retry settings
|
||||
const MIN_TIMEOUT = 10
|
||||
const MAX_RETRIES = 5
|
||||
const MAX_RETRY_AFTER = 20
|
||||
const FACTOR = 6
|
||||
|
||||
export { Response }
|
||||
|
||||
export interface RetryOpts {
|
||||
factor?: number
|
||||
maxTimeout?: number
|
||||
minTimeout?: number
|
||||
retries?: number
|
||||
}
|
||||
|
||||
interface URLLike {
|
||||
href: string
|
||||
}
|
||||
|
||||
export type RequestInfo = string | URLLike | Request
|
||||
|
||||
export interface RequestInit extends NodeRequestInit {
|
||||
retry?: RetryOpts
|
||||
}
|
||||
|
||||
export const isRedirect = fetch.isRedirect
|
||||
|
||||
export default async function fetchRetry (url: RequestInfo, opts: RequestInit = {}): Promise<Response> {
|
||||
const retryOpts = Object.assign({
|
||||
factor: FACTOR,
|
||||
// timeouts will be [10, 60, 360, 2160, 12960]
|
||||
// (before randomization is added)
|
||||
maxRetryAfter: MAX_RETRY_AFTER,
|
||||
minTimeout: MIN_TIMEOUT,
|
||||
retries: MAX_RETRIES,
|
||||
}, opts.retry)
|
||||
|
||||
const op = retry.operation(retryOpts)
|
||||
|
||||
try {
|
||||
return await new Promise((resolve, reject) => op.attempt(async (attempt) => {
|
||||
try {
|
||||
// this will be retried
|
||||
const res = await fetch(url, opts)
|
||||
if ((res.status >= 500 && res.status < 600) || res.status === 429) {
|
||||
throw new ResponseError(res)
|
||||
} else {
|
||||
resolve(res)
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
const timeout = op.retry(error)
|
||||
if (timeout === false) {
|
||||
reject(op.mainError())
|
||||
return
|
||||
}
|
||||
requestRetryLogger.debug({
|
||||
attempt,
|
||||
error,
|
||||
maxRetries: retryOpts.retries,
|
||||
method: opts.method ?? 'GET',
|
||||
timeout,
|
||||
url: url.toString(),
|
||||
})
|
||||
}
|
||||
}))
|
||||
} catch (err) {
|
||||
if (err instanceof ResponseError) {
|
||||
return err.res
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
class ResponseError extends Error {
|
||||
public res: Response
|
||||
public code: number
|
||||
public status: number
|
||||
public statusCode: number
|
||||
public url: string
|
||||
constructor (res: Response) {
|
||||
super(res.statusText)
|
||||
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, ResponseError)
|
||||
}
|
||||
|
||||
this.name = this.constructor.name
|
||||
this.res = res
|
||||
|
||||
// backward compat
|
||||
this.code = this.status = this.statusCode = res.status
|
||||
this.url = res.url
|
||||
}
|
||||
}
|
||||
|
||||
exports.ResponseError = ResponseError
|
||||
@@ -1,14 +1,12 @@
|
||||
{
|
||||
"extends": "@pnpm/tsconfig",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"composite": false,
|
||||
"declaration": false,
|
||||
"outDir": "lib"
|
||||
"outDir": "lib",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"../../typings/**/*.d.ts"
|
||||
]
|
||||
],
|
||||
"references": []
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
"../../typings/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../fetch"
|
||||
},
|
||||
{
|
||||
"path": "../resolver-base"
|
||||
}
|
||||
|
||||
@@ -76,12 +76,12 @@
|
||||
"@types/mz": "^2.7.1",
|
||||
"@types/ncp": "^2.0.4",
|
||||
"@types/ramda": "^0.27.6",
|
||||
"@types/retry": "^0.12.0",
|
||||
"@types/semver": "^7.2.0",
|
||||
"@types/table": "^5.0.0",
|
||||
"@types/tape-promise": "^4.0.1",
|
||||
"@types/update-notifier": "^4.1.0",
|
||||
"@types/which": "^1.3.2",
|
||||
"@zkochan/retry": "^0.2.0",
|
||||
"@zkochan/rimraf": "1.0.0",
|
||||
"anonymous-npm-registry-client": "0.1.2",
|
||||
"byline": "5.0.0",
|
||||
@@ -101,7 +101,6 @@
|
||||
"path-exists": "4.0.0",
|
||||
"pnpm": "link:",
|
||||
"read-yaml-file": "2.0.0",
|
||||
"retry": "0.12.0",
|
||||
"semver": "^7.3.2",
|
||||
"symlink-dir": "^4.1.0",
|
||||
"tape-promise": "4.0.0",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import retry = require('@zkochan/retry')
|
||||
import loadJsonFile = require('load-json-file')
|
||||
import retry = require('retry')
|
||||
|
||||
export default <T>(filePath: string): Promise<T> => {
|
||||
const operation = retry.operation()
|
||||
const operation = retry.operation({})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
operation.attempt(async (currentAttempt) => {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
"../../typings/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../fetch"
|
||||
},
|
||||
{
|
||||
"path": "../store-controller-types"
|
||||
},
|
||||
|
||||
@@ -34,15 +34,16 @@
|
||||
"@pnpm/logger": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pnpm/core-loggers": "workspace:^4.0.2",
|
||||
"@pnpm/error": "workspace:1.2.0",
|
||||
"@pnpm/fetcher-base": "workspace:8.0.0",
|
||||
"@zkochan/retry": "^0.2.0",
|
||||
"credentials-by-uri": "2.0.0",
|
||||
"fetch-from-npm-registry": "workspace:4.0.3",
|
||||
"graceful-fs": "4.2.1",
|
||||
"mem": "^6.1.0",
|
||||
"mz": "2.7.0",
|
||||
"path-temp": "2.0.0",
|
||||
"retry": "0.12.0",
|
||||
"rimraf": "3.0.2",
|
||||
"ssri": "6.0.1"
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { requestRetryLogger } from '@pnpm/core-loggers'
|
||||
import PnpmError from '@pnpm/error'
|
||||
import {
|
||||
Cafs,
|
||||
@@ -5,12 +6,12 @@ import {
|
||||
FetchResult,
|
||||
FilesIndex,
|
||||
} from '@pnpm/fetcher-base'
|
||||
import * as retry from '@zkochan/retry'
|
||||
import createFetcher from 'fetch-from-npm-registry'
|
||||
import { IncomingMessage } from 'http'
|
||||
import fs = require('mz/fs')
|
||||
import path = require('path')
|
||||
import pathTemp = require('path-temp')
|
||||
import retry = require('retry')
|
||||
import rimraf = require('rimraf')
|
||||
import ssri = require('ssri')
|
||||
import urlLib = require('url')
|
||||
@@ -97,7 +98,12 @@ export default (
|
||||
userAgent?: string,
|
||||
}
|
||||
): DownloadFunction => {
|
||||
const fetchFromNpmRegistry = createFetcher(gotOpts)
|
||||
// The fetch library can retry requests on bad HTTP responses.
|
||||
// However, it is not enough to retry on bad HTTP responses only.
|
||||
// Requests should also be retried when the tarball's integrity check fails.
|
||||
// Hence, we tell fetch to not retry,
|
||||
// and we perform the retries from this function instead.
|
||||
const fetchFromNpmRegistry = createFetcher({ retry: { retries: 0 } })
|
||||
|
||||
const retryOpts = {
|
||||
factor: 10,
|
||||
@@ -130,19 +136,27 @@ export default (
|
||||
const op = retry.operation(retryOpts)
|
||||
|
||||
return new Promise<FetchResult>((resolve, reject) => {
|
||||
op.attempt((currentAttempt) => {
|
||||
fetch(currentAttempt)
|
||||
.then(resolve)
|
||||
.catch((err) => {
|
||||
if (err.httpStatusCode === 403) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
if (op.retry(err)) {
|
||||
return
|
||||
}
|
||||
op.attempt(async (attempt) => {
|
||||
try {
|
||||
resolve(await fetch(attempt))
|
||||
} catch (error) {
|
||||
if (error.httpStatusCode === 403) {
|
||||
reject(error)
|
||||
}
|
||||
const timeout = op.retry(error)
|
||||
if (timeout === false) {
|
||||
reject(op.mainError())
|
||||
return
|
||||
}
|
||||
requestRetryLogger.debug({
|
||||
attempt,
|
||||
error,
|
||||
maxRetries: retryOpts.retries,
|
||||
method: 'GET',
|
||||
timeout,
|
||||
url,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
58
pnpm-lock.yaml
generated
58
pnpm-lock.yaml
generated
@@ -247,6 +247,7 @@ importers:
|
||||
most: 1.8.1_most@1.8.1
|
||||
normalize-path: 3.0.0
|
||||
pretty-bytes: 5.3.0
|
||||
pretty-ms: 7.0.0
|
||||
pretty-time: 1.1.0
|
||||
ramda: 0.27.0
|
||||
right-pad: 1.0.1
|
||||
@@ -289,6 +290,7 @@ importers:
|
||||
normalize-newline: 3.0.0
|
||||
normalize-path: 3.0.0
|
||||
pretty-bytes: 5.3.0
|
||||
pretty-ms: ^7.0.0
|
||||
pretty-time: 1.1.0
|
||||
ramda: 0.27.0
|
||||
right-pad: 1.0.1
|
||||
@@ -368,15 +370,19 @@ importers:
|
||||
specifiers: {}
|
||||
packages/fetch:
|
||||
dependencies:
|
||||
'@zeit/fetch-retry': 5.0.0_node-fetch@2.6.0
|
||||
'@pnpm/core-loggers': 'link:../core-loggers'
|
||||
'@zkochan/retry': 0.2.0
|
||||
node-fetch: 2.6.0
|
||||
node-fetch-unix: 2.3.0
|
||||
devDependencies:
|
||||
'@pnpm/logger': 3.2.2
|
||||
'@types/node-fetch': 2.5.7
|
||||
cpy-cli: 3.1.1
|
||||
specifiers:
|
||||
'@pnpm/core-loggers': 'workspace:^4.0.2'
|
||||
'@pnpm/logger': ^3.2.2
|
||||
'@types/node-fetch': ^2.5.7
|
||||
'@zeit/fetch-retry': 5.0.0
|
||||
'@zkochan/retry': ^0.2.0
|
||||
cpy-cli: ^3.1.1
|
||||
node-fetch: 2.6.0
|
||||
node-fetch-unix: 2.3.0
|
||||
@@ -2140,12 +2146,12 @@ importers:
|
||||
'@types/mz': 2.7.1
|
||||
'@types/ncp': 2.0.4
|
||||
'@types/ramda': 0.27.6
|
||||
'@types/retry': 0.12.0
|
||||
'@types/semver': 7.2.0
|
||||
'@types/table': 5.0.0
|
||||
'@types/tape-promise': 4.0.1
|
||||
'@types/update-notifier': 4.1.0
|
||||
'@types/which': 1.3.2
|
||||
'@zkochan/retry': 0.2.0
|
||||
'@zkochan/rimraf': 1.0.0
|
||||
anonymous-npm-registry-client: 0.1.2
|
||||
byline: 5.0.0
|
||||
@@ -2165,7 +2171,6 @@ importers:
|
||||
path-exists: 4.0.0
|
||||
pnpm: 'link:'
|
||||
read-yaml-file: 2.0.0
|
||||
retry: 0.12.0
|
||||
semver: 7.3.2
|
||||
symlink-dir: 4.1.0
|
||||
tape-promise: 4.0.0
|
||||
@@ -2218,13 +2223,13 @@ importers:
|
||||
'@types/ncp': ^2.0.4
|
||||
'@types/nopt': ^3.0.29
|
||||
'@types/ramda': ^0.27.6
|
||||
'@types/retry': ^0.12.0
|
||||
'@types/semver': ^7.2.0
|
||||
'@types/table': ^5.0.0
|
||||
'@types/tape-promise': ^4.0.1
|
||||
'@types/update-notifier': ^4.1.0
|
||||
'@types/which': ^1.3.2
|
||||
'@zkochan/libnpx': 11.0.3
|
||||
'@zkochan/retry': ^0.2.0
|
||||
'@zkochan/rimraf': 1.0.0
|
||||
anonymous-npm-registry-client: 0.1.2
|
||||
byline: 5.0.0
|
||||
@@ -2253,7 +2258,6 @@ importers:
|
||||
ramda: 0.27.0
|
||||
read-yaml-file: 2.0.0
|
||||
render-help: 1.0.0
|
||||
retry: 0.12.0
|
||||
semver: ^7.3.2
|
||||
split-cmd: 1.0.1
|
||||
symlink-dir: ^4.1.0
|
||||
@@ -2764,15 +2768,16 @@ importers:
|
||||
symlink-dir: ^4.1.0
|
||||
packages/tarball-fetcher:
|
||||
dependencies:
|
||||
'@pnpm/core-loggers': 'link:../core-loggers'
|
||||
'@pnpm/error': 'link:../error'
|
||||
'@pnpm/fetcher-base': 'link:../fetcher-base'
|
||||
'@zkochan/retry': 0.2.0
|
||||
credentials-by-uri: 2.0.0
|
||||
fetch-from-npm-registry: 'link:../fetch-from-npm-registry'
|
||||
graceful-fs: 4.2.1
|
||||
mem: 6.1.0
|
||||
mz: 2.7.0
|
||||
path-temp: 2.0.0
|
||||
retry: 0.12.0
|
||||
rimraf: 3.0.2
|
||||
ssri: 6.0.1
|
||||
devDependencies:
|
||||
@@ -2790,6 +2795,7 @@ importers:
|
||||
tempy: 0.5.0
|
||||
specifiers:
|
||||
'@pnpm/cafs': 'workspace:1.0.1'
|
||||
'@pnpm/core-loggers': 'workspace:^4.0.2'
|
||||
'@pnpm/error': 'workspace:1.2.0'
|
||||
'@pnpm/fetcher-base': 'workspace:8.0.0'
|
||||
'@pnpm/logger': 3.2.2
|
||||
@@ -2800,6 +2806,7 @@ importers:
|
||||
'@types/retry': ^0.12.0
|
||||
'@types/rimraf': ^3.0.0
|
||||
'@types/ssri': ^6.0.3
|
||||
'@zkochan/retry': ^0.2.0
|
||||
cp-file: 9.0.0
|
||||
credentials-by-uri: 2.0.0
|
||||
fetch-from-npm-registry: 'workspace:4.0.3'
|
||||
@@ -2808,7 +2815,6 @@ importers:
|
||||
mz: 2.7.0
|
||||
nock: 12.0.3
|
||||
path-temp: 2.0.0
|
||||
retry: 0.12.0
|
||||
rimraf: 3.0.2
|
||||
ssri: 6.0.1
|
||||
tempy: 0.5.0
|
||||
@@ -3840,16 +3846,6 @@ packages:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
|
||||
/@zeit/fetch-retry/5.0.0_node-fetch@2.6.0:
|
||||
dependencies:
|
||||
async-retry: 1.3.1
|
||||
debug: 3.2.6
|
||||
node-fetch: 2.6.0
|
||||
dev: false
|
||||
peerDependencies:
|
||||
node-fetch: '*'
|
||||
resolution:
|
||||
integrity: sha512-48tgGYYNX4AGyR8LZa5nMGdr3j4VXYxAA7BX6RWSKIWZkdh1bbkUB6M9ZLfmxsED0CEGpJmP7svN8qnolwZ45w==
|
||||
/@zkochan/cmd-shim/4.3.0:
|
||||
dependencies:
|
||||
is-windows: 1.0.2
|
||||
@@ -3913,6 +3909,11 @@ packages:
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-9hHFHZTOexP/oge2GMQzPlhdi9IJ+Zgnobh7sNfSdIZepULMM/lNQE4hmkFDC2zk8+OBibtfHbUPulNZI18TQA==
|
||||
/@zkochan/retry/0.2.0:
|
||||
engines:
|
||||
node: '>=10'
|
||||
resolution:
|
||||
integrity: sha512-WhB+2B/ZPlW2Xy/kMJBrMbqecWXcbDDgn0K0wKBAgO2OlBTz1iLJrRWduo+DGGn0Akvz1Lu4Xvls7dJojximWw==
|
||||
/@zkochan/rimraf/1.0.0:
|
||||
dependencies:
|
||||
'@types/glob': 7.1.2
|
||||
@@ -4593,12 +4594,6 @@ packages:
|
||||
node: '>=4'
|
||||
resolution:
|
||||
integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
|
||||
/async-retry/1.3.1:
|
||||
dependencies:
|
||||
retry: 0.12.0
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==
|
||||
/async/3.2.0:
|
||||
dev: true
|
||||
resolution:
|
||||
@@ -9751,6 +9746,12 @@ packages:
|
||||
node: '>=8'
|
||||
resolution:
|
||||
integrity: sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==
|
||||
/parse-ms/2.1.0:
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==
|
||||
/parse-npm-tarball-url/3.0.0:
|
||||
dependencies:
|
||||
semver: 6.3.0
|
||||
@@ -9999,6 +10000,14 @@ packages:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==
|
||||
/pretty-ms/7.0.0:
|
||||
dependencies:
|
||||
parse-ms: 2.1.0
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=10'
|
||||
resolution:
|
||||
integrity: sha512-J3aPWiC5e9ZeZFuSeBraGxSkGMOvulSWsxDByOcbD1Pr75YL3LSNIKIb52WXbCLE1sS5s4inBBbryjF4Y05Ceg==
|
||||
/pretty-time/1.1.0:
|
||||
dev: false
|
||||
engines:
|
||||
@@ -10788,6 +10797,7 @@ packages:
|
||||
resolution:
|
||||
integrity: sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
|
||||
/retry/0.12.0:
|
||||
dev: false
|
||||
engines:
|
||||
node: '>= 4'
|
||||
resolution:
|
||||
|
||||
@@ -18,7 +18,7 @@ const repoRoot = path.join(__dirname, '../../..')
|
||||
if (isSubdir(pkgsDir, dir)) {
|
||||
await writeProjectManifest(await updateManifest(dir, manifest))
|
||||
}
|
||||
if (manifest.name === '@pnpm/fetch' || manifest.name === '@pnpm/tsconfig') continue
|
||||
if (manifest.name === '@pnpm/tsconfig') continue
|
||||
const relative = path.relative(repoRoot, dir)
|
||||
const importer = lockfile.importers[relative]
|
||||
if (!importer) continue
|
||||
@@ -30,7 +30,7 @@ const repoRoot = path.join(__dirname, '../../..')
|
||||
}
|
||||
const references = [] as Array<{ path: string }>
|
||||
for (const spec of Object.values(deps)) {
|
||||
if (!spec.startsWith('link:') || spec.length === 5 || spec === 'link:../fetch') continue
|
||||
if (!spec.startsWith('link:') || spec.length === 5) continue
|
||||
references.push({ path: spec.substr(5) })
|
||||
}
|
||||
const tsConfig = await loadJsonFile<Object>(tsconfigLoc)
|
||||
@@ -94,11 +94,7 @@ async function updateManifest (dir: string, manifest: ProjectManifest) {
|
||||
}
|
||||
break
|
||||
}
|
||||
if (manifest.name === '@pnpm/fetch') {
|
||||
scripts.compile = 'rimraf lib && tsc && cpy src/**/*.d.ts lib'
|
||||
} else {
|
||||
scripts.compile = 'rimraf lib tsconfig.tsbuildinfo && tsc --build'
|
||||
}
|
||||
scripts.compile = 'rimraf lib tsconfig.tsbuildinfo && tsc --build'
|
||||
delete scripts.tsc
|
||||
let homepage: string
|
||||
let repository: string | { type: 'git', url: string }
|
||||
|
||||
Reference in New Issue
Block a user