@pnpm/resolving.git-resolver 1100.1.15 → 1100.1.17
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 +39 -0
- package/lib/index.js +52 -5
- package/lib/lsRemote.d.ts +4 -0
- package/lib/lsRemote.js +38 -7
- package/lib/parseBareSpecifier.js +64 -46
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @pnpm/git-resolver
|
|
2
2
|
|
|
3
|
+
## 1100.1.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- A git dependency whose `git ls-remote` fails now reports the `ERR_PNPM_GIT_RESOLVE_FAILED` code, naming the dependency instead of printing a bare `git` invocation, with credentials in the repository URL redacted. A specifier that does not ask for SSH resolves over HTTPS, because the URL recorded in the lockfile has to work on every machine that installs it, so the error explains how to substitute the transport on a machine that can only reach the host over SSH (`git config --global url."git@<host>:".insteadOf "https://<host>/"`) [#13743](https://github.com/pnpm/pnpm/issues/13743).
|
|
8
|
+
|
|
9
|
+
A missing `git` executable is reported as one, instead of surfacing the raw failure to start the process.
|
|
10
|
+
|
|
11
|
+
Credentials embedded in a git specifier are redacted from the "Could not resolve \<ref\> to a commit of \<repo\>" errors too.
|
|
12
|
+
|
|
13
|
+
Resolving a public repository makes one `git ls-remote` round-trip instead of two.
|
|
14
|
+
|
|
15
|
+
- An `ssh://` git dependency pointing at a bracketed IPv6 host, such as `ssh://[::1]/repo.git`, is resolved now. Its colons were read as an SCP-style path separator, which turned the address into `[:/1]` and left the specifier unresolvable. Applies to both the TypeScript CLI and pacquet.
|
|
16
|
+
|
|
17
|
+
In the TypeScript CLI, an `ssh://` git dependency written without user info — `ssh://git.example.com/team/repo.git`, `git+ssh://git.example.com:2222/team/repo.git` — no longer fails with `TypeError: Cannot read properties of undefined (reading 'includes')`. Only the `user@host` form worked before.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies:
|
|
20
|
+
- @pnpm/error@1100.1.2
|
|
21
|
+
- @pnpm/network.fetch@1100.1.12
|
|
22
|
+
|
|
23
|
+
## 1100.1.16
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- Fixed a CI regression where `github:owner/repo` dependencies (and other shorthand Git specifiers) would fail to install with `Permission denied (publickey)` on CI runners that lack SSH keys. The Git resolver no longer records an SSH URL unless the user explicitly wrote one (e.g. `git+ssh://` or `git@host:...`):
|
|
28
|
+
|
|
29
|
+
- The repository visibility probe (an HTTP HEAD request) now retries transient failures such as `429 Too Many Requests`, so host throttling of CI runners is no longer mistaken for a private repository.
|
|
30
|
+
- For non-SSH specifiers, anonymous HTTPS `git ls-remote` access is now tried before SSH, so a public repository whose visibility probe fails still resolves to a portable HTTPS URL instead of an SSH URL that only works where SSH keys are configured.
|
|
31
|
+
- When every probe fails, the resolver falls back to HTTPS for shorthand and HTTPS-style specifiers, and only guesses SSH when the user explicitly provided an SSH URL.
|
|
32
|
+
- A repository that could not be confirmed public is no longer resolved to the host's anonymous archive URL (e.g. `codeload.github.com`, which would fail to download for a private repository); it stays a regular `git` resolution so installs can use ambient Git credentials such as credential helpers and tokens.
|
|
33
|
+
|
|
34
|
+
Note that a private repository that is reachable both over authenticated HTTPS and over SSH now resolves to its HTTPS URL, where previous versions recorded the SSH URL.
|
|
35
|
+
|
|
36
|
+
Fixes [pnpm/pnpm#13276](https://github.com/pnpm/pnpm/issues/13276).
|
|
37
|
+
|
|
38
|
+
<!-- cspell:ignore publickey -->
|
|
39
|
+
|
|
40
|
+
- Resolving a private git repository no longer blocks on an interactive credential prompt: `git ls-remote` now fails fast with an authentication error when git has no credentials for the repository [#13522](https://github.com/pnpm/pnpm/issues/13522).
|
|
41
|
+
|
|
3
42
|
## 1100.1.15
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import util from 'node:util';
|
|
3
|
+
import { PnpmError, redactAndSanitize } from '@pnpm/error';
|
|
2
4
|
import semver from 'semver';
|
|
3
5
|
import { createGitHostedPkgId } from './createGitHostedPkgId.js';
|
|
4
6
|
import { lsRemote } from './lsRemote.js';
|
|
@@ -33,7 +35,14 @@ export function createGitResolver(opts) {
|
|
|
33
35
|
const bareSpecifier = parsedSpec.gitCommittish == null || parsedSpec.gitCommittish === ''
|
|
34
36
|
? 'HEAD'
|
|
35
37
|
: parsedSpec.gitCommittish;
|
|
36
|
-
|
|
38
|
+
let commit;
|
|
39
|
+
try {
|
|
40
|
+
commit = await resolveRef(parsedSpec.fetchSpec, bareSpecifier, parsedSpec.gitRange);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
assert(util.types.isNativeError(err));
|
|
44
|
+
throw gitResolveError(err, wantedDependency.bareSpecifier, parsedSpec.fetchSpec);
|
|
45
|
+
}
|
|
37
46
|
let resolution;
|
|
38
47
|
if ((parsedSpec.hosted != null) && !isSsh(parsedSpec.fetchSpec)) {
|
|
39
48
|
// don't use tarball for ssh url, they are likely private repo
|
|
@@ -99,7 +108,6 @@ export async function getRepoRefs(repo, ref) {
|
|
|
99
108
|
// This is needed because annotated tags have their own SHA, and we need the commit SHA they point to
|
|
100
109
|
gitArgs.push(`${ref}^{}`);
|
|
101
110
|
}
|
|
102
|
-
// graceful-git by default retries 10 times, reduce to single retry
|
|
103
111
|
const result = await lsRemote(gitArgs, { retries: 1 });
|
|
104
112
|
const refs = {};
|
|
105
113
|
for (const line of result.stdout.split('\n')) {
|
|
@@ -136,7 +144,7 @@ function resolveRefFromRefs(refs, repo, ref, committish, range) {
|
|
|
136
144
|
commitId = commits[0];
|
|
137
145
|
}
|
|
138
146
|
else {
|
|
139
|
-
throw new Error(`Could not resolve ${ref} to a commit of ${repo}.`);
|
|
147
|
+
throw new Error(`Could not resolve ${ref} to a commit of ${redactAndSanitize(repo)}.`);
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
return commitId;
|
|
@@ -156,11 +164,50 @@ function resolveRefFromRefs(refs, repo, ref, committish, range) {
|
|
|
156
164
|
(refs[`refs/tags/${refVTag}^{}`] || // prefer annotated tags
|
|
157
165
|
refs[`refs/tags/${refVTag}`]);
|
|
158
166
|
if (!commitId) {
|
|
159
|
-
throw new Error(`Could not resolve ${range} to a commit of ${repo}. Available versions are: ${vTags.join(', ')}`);
|
|
167
|
+
throw new Error(`Could not resolve ${range} to a commit of ${redactAndSanitize(repo)}. Available versions are: ${vTags.join(', ')}`);
|
|
160
168
|
}
|
|
161
169
|
return commitId;
|
|
162
170
|
}
|
|
163
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Restate a failed `git ls-remote` as `ERR_PNPM_GIT_RESOLVE_FAILED`, naming the
|
|
174
|
+
* dependency it was resolving. Errors that describe the refs the remote did
|
|
175
|
+
* return (an unknown ref, an ambiguous commit-ish) already say which repository
|
|
176
|
+
* they came from and are left alone.
|
|
177
|
+
*/
|
|
178
|
+
function gitResolveError(err, bareSpecifier, repo) {
|
|
179
|
+
if (err.code !== 'ERR_PNPM_GIT_LS_REMOTE_FAILED')
|
|
180
|
+
return err;
|
|
181
|
+
return new PnpmError('GIT_RESOLVE_FAILED', `Failed to resolve git dependency "${redactAndSanitize(bareSpecifier)}": ${err.message}`, { hint: httpsTransportHint(repo) });
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Guidance for a specifier that resolved over HTTPS on a machine whose git
|
|
185
|
+
* cannot use that transport, or `undefined` when the resolution already went
|
|
186
|
+
* over SSH — there, the transport that failed is the one the specifier asked
|
|
187
|
+
* for.
|
|
188
|
+
*
|
|
189
|
+
* Substituting the transport is git's job rather than pnpm's: the URL pnpm
|
|
190
|
+
* records has to work for every machine that installs the lockfile, while
|
|
191
|
+
* `insteadOf` rewrites it for this one only.
|
|
192
|
+
*/
|
|
193
|
+
function httpsTransportHint(repo) {
|
|
194
|
+
let url;
|
|
195
|
+
try {
|
|
196
|
+
url = new URL(repo);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
if (url.protocol !== 'https:' && url.protocol !== 'http:')
|
|
202
|
+
return undefined;
|
|
203
|
+
const host = redactAndSanitize(url.host);
|
|
204
|
+
const hostname = redactAndSanitize(url.hostname);
|
|
205
|
+
return `pnpm resolves this specifier over HTTPS because it does not ask for SSH, and the URL it records has to work on every machine that installs the lockfile.
|
|
206
|
+
|
|
207
|
+
If git can only reach ${hostname} over SSH here, substitute the transport locally, leaving the recorded URL alone:
|
|
208
|
+
|
|
209
|
+
git config --global url."git@${hostname}:".insteadOf "${url.protocol}//${host}/"`;
|
|
210
|
+
}
|
|
164
211
|
function isSsh(gitSpec) {
|
|
165
212
|
return gitSpec.slice(0, 10) === 'git+ssh://' ||
|
|
166
213
|
gitSpec.slice(0, 4) === 'git@';
|
package/lib/lsRemote.d.ts
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Runs `git ls-remote` with interactive credential prompts disabled, so it
|
|
3
3
|
* fails fast on private repos instead of blocking on user input. All
|
|
4
4
|
* ls-remote invocations must go through this function to keep that guarantee.
|
|
5
|
+
*
|
|
6
|
+
* Failed runs are retried immediately, matching the Rust runner's policy.
|
|
7
|
+
* A run that fails every attempt throws `ERR_PNPM_GIT_LS_REMOTE_FAILED`,
|
|
8
|
+
* which the git resolver restates with the dependency it was resolving.
|
|
5
9
|
*/
|
|
6
10
|
export declare function lsRemote(args: string[], opts: {
|
|
7
11
|
retries: number;
|
package/lib/lsRemote.js
CHANGED
|
@@ -1,15 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PnpmError, redactAndSanitizeMultiline } from '@pnpm/error';
|
|
2
|
+
import { safeExeca as execa } from 'execa';
|
|
2
3
|
/**
|
|
3
4
|
* Runs `git ls-remote` with interactive credential prompts disabled, so it
|
|
4
5
|
* fails fast on private repos instead of blocking on user input. All
|
|
5
6
|
* ls-remote invocations must go through this function to keep that guarantee.
|
|
7
|
+
*
|
|
8
|
+
* Failed runs are retried immediately, matching the Rust runner's policy.
|
|
9
|
+
* A run that fails every attempt throws `ERR_PNPM_GIT_LS_REMOTE_FAILED`,
|
|
10
|
+
* which the git resolver restates with the dependency it was resolving.
|
|
6
11
|
*/
|
|
7
12
|
export async function lsRemote(args, opts) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
let lastErr;
|
|
14
|
+
for (let attempt = 0; attempt <= opts.retries; attempt++) {
|
|
15
|
+
try {
|
|
16
|
+
const { stdout } = await execa('git', ['ls-remote', ...args], {
|
|
17
|
+
// Snapshotted per call so changes to auth/proxy env vars made by a
|
|
18
|
+
// long-lived host process are picked up.
|
|
19
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
20
|
+
});
|
|
21
|
+
return { stdout: stdout };
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
lastErr = err;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
throw lsRemoteError(lastErr);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* git's stderr is untrusted: the repository URL it echoes back can carry
|
|
31
|
+
* `user:pass@` credentials, so it goes through
|
|
32
|
+
* {@link redactAndSanitizeMultiline} rather than being restated verbatim.
|
|
33
|
+
*/
|
|
34
|
+
function lsRemoteError(err) {
|
|
35
|
+
return new PnpmError('GIT_LS_REMOTE_FAILED', `git ls-remote failed: ${redactAndSanitizeMultiline(lsRemoteFailureDetail(err))}`);
|
|
36
|
+
}
|
|
37
|
+
function lsRemoteFailureDetail(err) {
|
|
38
|
+
if (err.code === 'ENOENT') {
|
|
39
|
+
return '`git` executable not found on PATH. Install git to resolve git-hosted packages.';
|
|
40
|
+
}
|
|
41
|
+
const stderr = err.stderr?.trim();
|
|
42
|
+
if (stderr != null && stderr !== '')
|
|
43
|
+
return stderr;
|
|
44
|
+
return err.message ?? String(err);
|
|
14
45
|
}
|
|
15
46
|
//# sourceMappingURL=lsRemote.js.map
|
|
@@ -49,53 +49,53 @@ function urlToFetchSpec(url) {
|
|
|
49
49
|
}
|
|
50
50
|
async function fromHostedGit(hosted, dispatcherOptions) {
|
|
51
51
|
let fetchSpec = null;
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const httpsUrl = hosted.https({ noCommittish: true, noGitPlus: true });
|
|
53
|
+
const sshUrl = hosted.ssh({ noCommittish: true });
|
|
54
|
+
// SSH is probed before the HTTPS fallbacks (and used as the last-resort guess)
|
|
55
|
+
// only when the user explicitly wrote an SSH URL. For every other representation
|
|
56
|
+
// (`shortcut`, `https`, ...) an SSH remote was never asked for, and recording one
|
|
57
|
+
// in the lockfile breaks installs in environments without SSH keys, so every
|
|
58
|
+
// HTTPS transport is exhausted first.
|
|
59
|
+
//
|
|
60
|
+
// Such a specifier therefore resolves over HTTPS whether or not git can reach
|
|
61
|
+
// the host that way on this machine, and its HTTPS access is not probed at all:
|
|
62
|
+
// the probe could not change what is recorded, and a machine that reaches the
|
|
63
|
+
// host only over SSH substitutes the transport itself through git's
|
|
64
|
+
// `url.<base>.insteadOf`. Only an explicit SSH URL, which HTTPS may displace,
|
|
65
|
+
// is worth the round-trip.
|
|
66
|
+
const preferSsh = hosted.default === 'sshurl';
|
|
67
|
+
const repoIsPublic = httpsUrl != null && await isRepoPublic(httpsUrl, dispatcherOptions);
|
|
68
|
+
if (httpsUrl && repoIsPublic && (!preferSsh || await accessRepository(httpsUrl))) {
|
|
69
|
+
fetchSpec = httpsUrl;
|
|
56
70
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (gitSshUrl && await accessRepository(gitSshUrl)) {
|
|
60
|
-
fetchSpec = gitSshUrl;
|
|
61
|
-
}
|
|
71
|
+
if (!fetchSpec && preferSsh && sshUrl && await accessRepository(sshUrl)) {
|
|
72
|
+
fetchSpec = sshUrl;
|
|
62
73
|
}
|
|
63
|
-
if (!fetchSpec) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// use HTTP HEAD request to test whether this is a private repo, to avoid login prompt.
|
|
82
|
-
// this is very similar to yarn classic's behavior.
|
|
83
|
-
// npm instead tries git ls-remote directly which prompts user for login credentials.
|
|
84
|
-
// HTTP HEAD on https://domain/user/repo, strip out ".git"
|
|
85
|
-
const response = await fetchWithDispatcher(httpsUrl.replace(/\.git$/, ''), { method: 'HEAD', redirect: 'manual', retry: { retries: 0 }, dispatcherOptions });
|
|
86
|
-
if (response.ok) {
|
|
87
|
-
fetchSpec = httpsUrl;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
// ignore
|
|
92
|
-
}
|
|
93
|
-
}
|
|
74
|
+
if (!fetchSpec && httpsUrl) {
|
|
75
|
+
if ((hosted.auth || !repoIsPublic) && await accessRepository(httpsUrl)) {
|
|
76
|
+
// Reachable over HTTPS without being provably public, so resolve as
|
|
77
|
+
// `type: git` against this exact URL: the host's archive endpoint would
|
|
78
|
+
// carry neither the URL's credentials nor ambient ones (helpers, tokens).
|
|
79
|
+
return {
|
|
80
|
+
fetchSpec: httpsUrl,
|
|
81
|
+
hosted: {
|
|
82
|
+
...hosted,
|
|
83
|
+
_fill: hosted._fill,
|
|
84
|
+
tarball: undefined,
|
|
85
|
+
},
|
|
86
|
+
normalizedBareSpecifier: `git+${httpsUrl}`,
|
|
87
|
+
...parseGitParams(hosted.committish),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (repoIsPublic) {
|
|
91
|
+
fetchSpec = httpsUrl;
|
|
94
92
|
}
|
|
95
93
|
}
|
|
94
|
+
if (!fetchSpec && !preferSsh && sshUrl && await accessRepository(sshUrl)) {
|
|
95
|
+
fetchSpec = sshUrl;
|
|
96
|
+
}
|
|
96
97
|
if (!fetchSpec) {
|
|
97
|
-
|
|
98
|
-
fetchSpec = hosted.sshurl({ noCommittish: true });
|
|
98
|
+
fetchSpec = preferSsh ? hosted.sshurl({ noCommittish: true }) : httpsUrl;
|
|
99
99
|
}
|
|
100
100
|
return {
|
|
101
101
|
fetchSpec: fetchSpec,
|
|
@@ -103,7 +103,10 @@ async function fromHostedGit(hosted, dispatcherOptions) {
|
|
|
103
103
|
...hosted,
|
|
104
104
|
tarballtemplate: hosted.type === 'gitlab' ? gitlabTarballTemplate : hosted.tarballtemplate,
|
|
105
105
|
_fill: hosted._fill,
|
|
106
|
-
|
|
106
|
+
// Same rationale as the early return above: without proof that the repo
|
|
107
|
+
// is public, the host's anonymous archive endpoint cannot be assumed to
|
|
108
|
+
// work, so the resolution must stay `type: git`.
|
|
109
|
+
tarball: repoIsPublic ? hosted.tarball : undefined,
|
|
107
110
|
},
|
|
108
111
|
normalizedBareSpecifier: hosted.shortcut(),
|
|
109
112
|
...parseGitParams(hosted.committish),
|
|
@@ -116,9 +119,20 @@ function gitlabTarballTemplate({ domain, user, project, committish }) {
|
|
|
116
119
|
const ref = committish ? encodeURIComponent(committish) : 'HEAD';
|
|
117
120
|
return `https://${domain}/${user}/${project}/-/archive/${ref}/${project}-${ref}.tar.gz`;
|
|
118
121
|
}
|
|
122
|
+
// An HTTP HEAD on the project page (without ".git") instead of `git ls-remote`:
|
|
123
|
+
// probing a private repo with ls-remote would trigger a credential prompt. This is
|
|
124
|
+
// very similar to yarn classic's behavior; npm instead tries git ls-remote directly,
|
|
125
|
+
// which prompts for login credentials. Transient failures (429/5xx/network errors)
|
|
126
|
+
// are retried by the fetch layer so registry throttling of CI runners is not
|
|
127
|
+
// mistaken for a private repository.
|
|
119
128
|
async function isRepoPublic(httpsUrl, dispatcherOptions) {
|
|
120
129
|
try {
|
|
121
|
-
const response = await fetchWithDispatcher(httpsUrl.replace(/\.git$/, ''), {
|
|
130
|
+
const response = await fetchWithDispatcher(httpsUrl.replace(/\.git$/, ''), {
|
|
131
|
+
method: 'HEAD',
|
|
132
|
+
redirect: 'manual',
|
|
133
|
+
retry: { retries: 2, factor: 2, minTimeout: 500, maxTimeout: 2_000 },
|
|
134
|
+
dispatcherOptions,
|
|
135
|
+
});
|
|
122
136
|
return response.ok;
|
|
123
137
|
}
|
|
124
138
|
catch {
|
|
@@ -165,8 +179,12 @@ function correctUrl(gitUrl) {
|
|
|
165
179
|
_gitUrl = _gitUrl.slice(0, hashIndex);
|
|
166
180
|
}
|
|
167
181
|
const [auth, ...pathname] = _gitUrl.slice(6).split('/');
|
|
168
|
-
const
|
|
169
|
-
|
|
182
|
+
const userInfoEnd = auth.lastIndexOf('@');
|
|
183
|
+
const host = userInfoEnd === -1 ? auth : auth.slice(userInfoEnd + 1);
|
|
184
|
+
// The colons of a bracketed IPv6 literal belong to the address.
|
|
185
|
+
const bracketEnd = host.startsWith('[') ? host.indexOf(']') : -1;
|
|
186
|
+
const afterHost = bracketEnd === -1 ? host : host.slice(bracketEnd + 1);
|
|
187
|
+
if (afterHost.includes(':') && !/:\d+$/.test(afterHost)) {
|
|
170
188
|
const authArr = auth.split(':');
|
|
171
189
|
const protocol = gitUrl.split('://')[0];
|
|
172
190
|
gitUrl = `${protocol}://${authArr.slice(0, -1).join(':') + '/' + authArr[authArr.length - 1]}${pathname.length ? '/' + pathname.join('/') : ''}${hash}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/resolving.git-resolver",
|
|
3
|
-
"version": "1100.1.
|
|
3
|
+
"version": "1100.1.17",
|
|
4
4
|
"description": "Resolver for git-hosted packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -29,19 +29,19 @@
|
|
|
29
29
|
"!*.map"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@pnpm/error": "1100.1.
|
|
33
|
-
"@pnpm/network.fetch": "1100.1.
|
|
32
|
+
"@pnpm/error": "1100.1.2",
|
|
33
|
+
"@pnpm/network.fetch": "1100.1.12",
|
|
34
34
|
"@pnpm/resolving.resolver-base": "1101.1.0",
|
|
35
|
-
"
|
|
35
|
+
"execa": "npm:safe-execa@0.3.0",
|
|
36
36
|
"hosted-git-info": "npm:@pnpm/hosted-git-info@1.0.0",
|
|
37
37
|
"semver": "^7.8.5"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@jest/globals": "30.4.1",
|
|
41
|
-
"@pnpm/resolving.git-resolver": "1100.1.
|
|
41
|
+
"@pnpm/resolving.git-resolver": "1100.1.17",
|
|
42
42
|
"@types/hosted-git-info": "^3.0.5",
|
|
43
43
|
"@types/is-windows": "^1.0.2",
|
|
44
|
-
"@types/semver": "7.
|
|
44
|
+
"@types/semver": "7.8.0",
|
|
45
45
|
"is-windows": "^1.0.2"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|