@pnpm/fetching.tarball-fetcher 1102.0.15 → 1102.1.1
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @pnpm/tarball-fetcher
|
|
2
2
|
|
|
3
|
+
## 1102.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Authenticate Node.js runtime downloads from `nodeDownloadMirrors` with URL-scoped npm registry credentials, including bearer tokens, basic auth, and `tokenHelper` [pnpm/pnpm#14334](https://github.com/pnpm/pnpm/issues/14334).
|
|
8
|
+
|
|
9
|
+
- Network and archive retry logs hide credentials and signed query parameters in request URLs.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies:
|
|
12
|
+
- @pnpm/error@1100.1.4
|
|
13
|
+
- @pnpm/exec.prepare-package@1100.0.35
|
|
14
|
+
- @pnpm/store.index@1100.3.1
|
|
15
|
+
|
|
16
|
+
## 1102.1.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- Added support for registry replacement tarballs using standard integrity values, explicit revision fields, registry routing from the `registries` setting, non-redirecting integrity-addressed URLs, canonical safe-integer revision numbers, and pnpr proxying for immutable upstream revision artifacts.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Enforce `allowBuilds` when a prepared git dependency is reused from the shared store, and use the lockfile's canonical git resolution ID in approval suggestions.
|
|
25
|
+
|
|
26
|
+
- Updated dependencies:
|
|
27
|
+
- @pnpm/core-loggers@1100.3.4
|
|
28
|
+
- @pnpm/exec.prepare-package@1100.0.34
|
|
29
|
+
- @pnpm/fetching.fetcher-base@1100.2.9
|
|
30
|
+
- @pnpm/fs.graceful-fs@1100.2.0
|
|
31
|
+
- @pnpm/store.index@1100.3.0
|
|
32
|
+
- @pnpm/types@1102.1.0
|
|
33
|
+
|
|
3
34
|
## 1102.0.15
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { PnpmError } from '@pnpm/error';
|
|
1
|
+
import { PnpmError, redactUrlForDisplay } from '@pnpm/error';
|
|
2
2
|
export class BadTarballError extends PnpmError {
|
|
3
3
|
expectedSize;
|
|
4
4
|
receivedSize;
|
|
5
5
|
constructor(opts) {
|
|
6
|
-
const message = `Actual size (${opts.receivedSize}) of tarball (${opts.tarballUrl}) did not match the one specified in 'Content-Length' header (${opts.expectedSize})`;
|
|
6
|
+
const message = `Actual size (${opts.receivedSize}) of tarball (${redactUrlForDisplay(opts.tarballUrl)}) did not match the one specified in 'Content-Length' header (${opts.expectedSize})`;
|
|
7
7
|
super('BAD_TARBALL_SIZE', message, {
|
|
8
8
|
attempts: opts?.attempts,
|
|
9
9
|
});
|
|
@@ -23,6 +23,7 @@ export function createGitHostedTarballFetcher(fetchRemoteTarball, fetcherOpts) {
|
|
|
23
23
|
filesMap: prepareResult.filesMap,
|
|
24
24
|
manifest: prepareResult.manifest ?? manifest,
|
|
25
25
|
requiresBuild,
|
|
26
|
+
requiresPrepare: prepareResult.requiresPrepare,
|
|
26
27
|
// Propagate the raw tarball integrity so the lockfile pins it and
|
|
27
28
|
// future installs detect a tampered tarball from the git host.
|
|
28
29
|
integrity,
|
|
@@ -49,7 +50,7 @@ async function prepareGitHostedPkg(filesMap, cafs, rawFilesIndexFile, filesIndex
|
|
|
49
50
|
const { shouldBeBuilt, pkgDir } = await preparePackage({
|
|
50
51
|
...opts,
|
|
51
52
|
allowBuild: fetcherOpts.allowBuild,
|
|
52
|
-
pkgResolutionId: createGitHostedTarballPkgResolutionId(resolution),
|
|
53
|
+
pkgResolutionId: fetcherOpts.pkgResolutionId ?? createGitHostedTarballPkgResolutionId(resolution),
|
|
53
54
|
}, tempLocation, resolution.path ?? '');
|
|
54
55
|
const files = await packlist(pkgDir);
|
|
55
56
|
const { storeIndex } = opts;
|
|
@@ -57,12 +58,14 @@ async function prepareGitHostedPkg(filesMap, cafs, rawFilesIndexFile, filesIndex
|
|
|
57
58
|
if (!shouldBeBuilt) {
|
|
58
59
|
const data = storeIndex.get(rawFilesIndexFile);
|
|
59
60
|
if (data) {
|
|
61
|
+
data.requiresPrepare = false;
|
|
60
62
|
storeIndex.set(filesIndexFile, data);
|
|
61
63
|
storeIndex.delete(rawFilesIndexFile);
|
|
62
64
|
}
|
|
63
65
|
return {
|
|
64
66
|
filesMap,
|
|
65
67
|
ignoredBuild: false,
|
|
68
|
+
requiresPrepare: false,
|
|
66
69
|
};
|
|
67
70
|
}
|
|
68
71
|
if (opts.ignoreScripts) {
|
|
@@ -70,6 +73,7 @@ async function prepareGitHostedPkg(filesMap, cafs, rawFilesIndexFile, filesIndex
|
|
|
70
73
|
return {
|
|
71
74
|
filesMap,
|
|
72
75
|
ignoredBuild: true,
|
|
76
|
+
requiresPrepare: true,
|
|
73
77
|
};
|
|
74
78
|
}
|
|
75
79
|
}
|
|
@@ -86,8 +90,10 @@ async function prepareGitHostedPkg(filesMap, cafs, rawFilesIndexFile, filesIndex
|
|
|
86
90
|
filesIndexFile,
|
|
87
91
|
pkg: fetcherOpts.pkg,
|
|
88
92
|
readManifest: fetcherOpts.readManifest,
|
|
93
|
+
requiresPrepare: shouldBeBuilt,
|
|
89
94
|
}),
|
|
90
95
|
ignoredBuild: Boolean(opts.ignoreScripts),
|
|
96
|
+
requiresPrepare: shouldBeBuilt,
|
|
91
97
|
};
|
|
92
98
|
}
|
|
93
99
|
function createGitHostedTarballPkgResolutionId(resolution) {
|
package/lib/index.js
CHANGED
|
@@ -46,6 +46,8 @@ async function fetchFromTarball(ctx, cafs, resolution, opts) {
|
|
|
46
46
|
registry: resolution.registry,
|
|
47
47
|
filesIndexFile: opts.filesIndexFile,
|
|
48
48
|
pkg: opts.pkg,
|
|
49
|
+
redirect: resolution.revision == null ? undefined : 'manual',
|
|
50
|
+
retry: resolution.revision == null ? undefined : { retries: 0 },
|
|
49
51
|
appendManifest: opts.appendManifest,
|
|
50
52
|
ignoreFilePattern: opts.ignoreFilePattern,
|
|
51
53
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IncomingMessage } from 'node:http';
|
|
2
2
|
import type { FetchOptions, FetchResult } from '@pnpm/fetching.fetcher-base';
|
|
3
|
-
import type { FetchFromRegistry, GetAuthHeader } from '@pnpm/fetching.types';
|
|
3
|
+
import type { FetchFromRegistry, GetAuthHeader, RetryTimeoutOptions } from '@pnpm/fetching.types';
|
|
4
4
|
import type { Cafs } from '@pnpm/store.cafs-types';
|
|
5
5
|
import type { StoreIndex } from '@pnpm/store.index';
|
|
6
6
|
export interface HttpResponse {
|
|
@@ -13,6 +13,8 @@ export type DownloadOptions = {
|
|
|
13
13
|
onStart?: (totalSize: number | null, attempt: number) => void;
|
|
14
14
|
onProgress?: (downloaded: number) => void;
|
|
15
15
|
integrity?: string;
|
|
16
|
+
redirect?: RequestRedirect;
|
|
17
|
+
retry?: Pick<RetryTimeoutOptions, 'retries'>;
|
|
16
18
|
storeIndex: StoreIndex;
|
|
17
19
|
pkg?: FetchOptions['pkg'];
|
|
18
20
|
} & Pick<FetchOptions, 'appendManifest' | 'readManifest' | 'filesIndexFile' | 'ignoreFilePattern'>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isIP } from 'node:net';
|
|
1
2
|
import util from 'node:util';
|
|
2
3
|
import { requestRetryLogger } from '@pnpm/core-loggers';
|
|
3
4
|
import { FetchError, redactUrlForDisplay } from '@pnpm/error';
|
|
@@ -17,15 +18,17 @@ export function createDownloader(fetchFromRegistry, gotOpts) {
|
|
|
17
18
|
};
|
|
18
19
|
const fetchMinSpeedKiBps = gotOpts.fetchMinSpeedKiBps ?? 50; // 50 KiB/s
|
|
19
20
|
return async function download(url, opts) {
|
|
20
|
-
const authHeaderValue = opts.getAuthHeaderByURI(url, { pkgName: opts.pkg?.name });
|
|
21
|
-
const
|
|
21
|
+
const authHeaderValue = getSecureNodeMirrorAuthHeader(opts.getAuthHeaderByURI(url, { pkgName: opts.pkg?.name }), url, opts.appendManifest?.name);
|
|
22
|
+
const downloadRetryOpts = { ...retryOpts, ...opts.retry };
|
|
23
|
+
const op = retry.operation(downloadRetryOpts);
|
|
22
24
|
return new Promise((resolve, reject) => {
|
|
23
25
|
op.attempt(async (attempt) => {
|
|
24
26
|
try {
|
|
25
27
|
resolve(await fetch(attempt));
|
|
26
28
|
}
|
|
27
29
|
catch (error) { // eslint-disable-line
|
|
28
|
-
if (error.response?.status
|
|
30
|
+
if ((opts.redirect === 'manual' && error.response?.status >= 300 && error.response.status < 400) ||
|
|
31
|
+
error.response?.status === 401 ||
|
|
29
32
|
error.response?.status === 403 ||
|
|
30
33
|
error.response?.status === 404 ||
|
|
31
34
|
error.code === 'ERR_PNPM_PREPARE_PKG_FAILURE') {
|
|
@@ -56,10 +59,10 @@ export function createDownloader(fetchFromRegistry, gotOpts) {
|
|
|
56
59
|
requestRetryLogger.debug({
|
|
57
60
|
attempt,
|
|
58
61
|
error: errorInfo,
|
|
59
|
-
maxRetries:
|
|
62
|
+
maxRetries: downloadRetryOpts.retries,
|
|
60
63
|
method: 'GET',
|
|
61
64
|
timeout,
|
|
62
|
-
url,
|
|
65
|
+
url: redactUrlForDisplay(url),
|
|
63
66
|
});
|
|
64
67
|
}
|
|
65
68
|
});
|
|
@@ -79,6 +82,7 @@ export function createDownloader(fetchFromRegistry, gotOpts) {
|
|
|
79
82
|
// Hence, we tell fetch to not retry,
|
|
80
83
|
// and we perform the retries from this function instead.
|
|
81
84
|
retry: { retries: 0 },
|
|
85
|
+
redirect: opts.redirect,
|
|
82
86
|
timeout: gotOpts.timeout,
|
|
83
87
|
});
|
|
84
88
|
if (res.status !== 200) {
|
|
@@ -170,6 +174,17 @@ export function createDownloader(fetchFromRegistry, gotOpts) {
|
|
|
170
174
|
}
|
|
171
175
|
};
|
|
172
176
|
}
|
|
177
|
+
function getSecureNodeMirrorAuthHeader(authHeaderValue, url, appendedPackageName) {
|
|
178
|
+
if (authHeaderValue == null || appendedPackageName !== 'node')
|
|
179
|
+
return authHeaderValue;
|
|
180
|
+
const parsed = new URL(url);
|
|
181
|
+
if (parsed.protocol === 'https:' || isLoopbackHost(parsed.hostname))
|
|
182
|
+
return authHeaderValue;
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
function isLoopbackHost(hostname) {
|
|
186
|
+
return hostname === 'localhost' || hostname === '[::1]' || (isIP(hostname) === 4 && hostname.startsWith('127.'));
|
|
187
|
+
}
|
|
173
188
|
// Per RFC 9110 §8.4, Content-Encoding is a comma-separated list of codings.
|
|
174
189
|
// The response is encoded unless every coding is `identity` (case-insensitive,
|
|
175
190
|
// surrounding whitespace ignored).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/fetching.tarball-fetcher",
|
|
3
|
-
"version": "1102.
|
|
3
|
+
"version": "1102.1.1",
|
|
4
4
|
"description": "Fetcher for packages hosted as tarballs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -29,33 +29,33 @@
|
|
|
29
29
|
"!*.map"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@pnpm/core-loggers": "1100.3.
|
|
33
|
-
"@pnpm/error": "1100.1.
|
|
34
|
-
"@pnpm/exec.prepare-package": "1100.0.
|
|
35
|
-
"@pnpm/fetching.fetcher-base": "1100.2.
|
|
32
|
+
"@pnpm/core-loggers": "1100.3.4",
|
|
33
|
+
"@pnpm/error": "1100.1.4",
|
|
34
|
+
"@pnpm/exec.prepare-package": "1100.0.35",
|
|
35
|
+
"@pnpm/fetching.fetcher-base": "1100.2.9",
|
|
36
36
|
"@pnpm/fetching.types": "1100.0.3",
|
|
37
|
-
"@pnpm/fs.graceful-fs": "1100.
|
|
37
|
+
"@pnpm/fs.graceful-fs": "1100.2.0",
|
|
38
38
|
"@pnpm/fs.packlist": "1100.0.4",
|
|
39
|
-
"@pnpm/store.index": "1100.
|
|
40
|
-
"@pnpm/types": "1102.
|
|
39
|
+
"@pnpm/store.index": "1100.3.1",
|
|
40
|
+
"@pnpm/types": "1102.1.0",
|
|
41
41
|
"@zkochan/retry": "^0.2.0",
|
|
42
42
|
"lodash.throttle": "4.1.1",
|
|
43
43
|
"ramda": "npm:@pnpm/ramda@0.28.1"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@pnpm/logger": "^1100.0.0",
|
|
47
|
-
"@pnpm/worker": "^1100.
|
|
47
|
+
"@pnpm/worker": "^1100.4.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@jest/globals": "30.4.1",
|
|
51
|
-
"@pnpm/fetching.tarball-fetcher": "1102.
|
|
51
|
+
"@pnpm/fetching.tarball-fetcher": "1102.1.1",
|
|
52
52
|
"@pnpm/logger": "1100.0.0",
|
|
53
|
-
"@pnpm/network.fetch": "1100.1.
|
|
54
|
-
"@pnpm/store.cafs-types": "1100.0
|
|
55
|
-
"@pnpm/store.create-cafs-store": "1100.0.
|
|
53
|
+
"@pnpm/network.fetch": "1100.1.15",
|
|
54
|
+
"@pnpm/store.cafs-types": "1100.1.0",
|
|
55
|
+
"@pnpm/store.create-cafs-store": "1100.0.28",
|
|
56
56
|
"@pnpm/test-fixtures": "1100.0.1",
|
|
57
57
|
"@pnpm/text.ordinal-comparator": "1100.0.0",
|
|
58
|
-
"@pnpm/types": "1102.
|
|
58
|
+
"@pnpm/types": "1102.1.0",
|
|
59
59
|
"@types/lodash.throttle": "4.1.9",
|
|
60
60
|
"@types/ramda": "0.32.0",
|
|
61
61
|
"@types/retry": "^0.12.5",
|