@pnpm/resolving.npm-resolver 1101.3.3 → 1101.5.0
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/lib/createNpmResolutionVerifier.d.ts +9 -6
- package/lib/createNpmResolutionVerifier.js +124 -30
- package/lib/pickPackage.js +1 -1
- package/lib/trustChecks.d.ts +1 -1
- package/lib/trustChecks.js +10 -3
- package/lib/violationCodes.d.ts +1 -0
- package/lib/violationCodes.js +1 -0
- package/package.json +23 -20
|
@@ -71,15 +71,18 @@ export interface CreateNpmResolutionVerifierOptions {
|
|
|
71
71
|
now?: number;
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
|
-
* Returns a `ResolutionVerifier`
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
74
|
+
* Returns a `ResolutionVerifier` for npm-registry-resolved lockfile
|
|
75
|
+
* entries. It always binds each entry's recorded tarball URL to the
|
|
76
|
+
* artifact the registry's metadata lists (an anti-tamper check that does
|
|
77
|
+
* not depend on any policy), and additionally re-applies the
|
|
78
|
+
* `minimumReleaseAge` and/or `trustPolicy='no-downgrade'` policies when
|
|
79
|
+
* those are configured. Pairs with `createNpmResolver`: each resolver
|
|
80
|
+
* factory may export a sibling verifier factory that the default-resolver
|
|
81
|
+
* combines.
|
|
79
82
|
*
|
|
80
83
|
* Designed for fail-closed semantics: if the manifest can't be loaded or
|
|
81
84
|
* the pinned version is missing from it, the verifier reports a violation
|
|
82
85
|
* rather than silently passing. Mirrors the post-resolution gate bun added
|
|
83
86
|
* for the same shape of bug in oven-sh/bun#30526.
|
|
84
87
|
*/
|
|
85
|
-
export declare function createNpmResolutionVerifier(opts: CreateNpmResolutionVerifierOptions): ResolutionVerifier
|
|
88
|
+
export declare function createNpmResolutionVerifier(opts: CreateNpmResolutionVerifierOptions): ResolutionVerifier;
|
|
@@ -5,16 +5,20 @@ import { PnpmError } from '@pnpm/error';
|
|
|
5
5
|
import semver from 'semver';
|
|
6
6
|
import { fetchAttestationPublishedAt } from './fetchAttestationPublishedAt.js';
|
|
7
7
|
import { fetchAbbreviatedMetadataCached, fetchFullMetadataCached, } from './fetchFullMetadataCached.js';
|
|
8
|
+
import { normalizeRegistryUrl } from './normalizeRegistryUrl.js';
|
|
8
9
|
import { BUILTIN_NAMED_REGISTRIES } from './parseBareSpecifier.js';
|
|
9
10
|
import { getPkgMirrorPath, loadMeta, warnMissingTimeFieldOnce } from './pickPackage.js';
|
|
10
11
|
import { failIfTrustDowngraded } from './trustChecks.js';
|
|
11
|
-
import { MINIMUM_RELEASE_AGE_VIOLATION_CODE, TRUST_DOWNGRADE_VIOLATION_CODE, } from './violationCodes.js';
|
|
12
|
+
import { MINIMUM_RELEASE_AGE_VIOLATION_CODE, TARBALL_URL_MISMATCH_VIOLATION_CODE, TRUST_DOWNGRADE_VIOLATION_CODE, } from './violationCodes.js';
|
|
12
13
|
/**
|
|
13
|
-
* Returns a `ResolutionVerifier`
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* Returns a `ResolutionVerifier` for npm-registry-resolved lockfile
|
|
15
|
+
* entries. It always binds each entry's recorded tarball URL to the
|
|
16
|
+
* artifact the registry's metadata lists (an anti-tamper check that does
|
|
17
|
+
* not depend on any policy), and additionally re-applies the
|
|
18
|
+
* `minimumReleaseAge` and/or `trustPolicy='no-downgrade'` policies when
|
|
19
|
+
* those are configured. Pairs with `createNpmResolver`: each resolver
|
|
20
|
+
* factory may export a sibling verifier factory that the default-resolver
|
|
21
|
+
* combines.
|
|
18
22
|
*
|
|
19
23
|
* Designed for fail-closed semantics: if the manifest can't be loaded or
|
|
20
24
|
* the pinned version is missing from it, the verifier reports a violation
|
|
@@ -24,10 +28,6 @@ import { MINIMUM_RELEASE_AGE_VIOLATION_CODE, TRUST_DOWNGRADE_VIOLATION_CODE, } f
|
|
|
24
28
|
export function createNpmResolutionVerifier(opts) {
|
|
25
29
|
const ageCheckActive = Boolean(opts.minimumReleaseAge);
|
|
26
30
|
const trustCheckActive = opts.trustPolicy === 'no-downgrade';
|
|
27
|
-
// No policy → no verifier. Skipping early keeps the install-side fan-out
|
|
28
|
-
// empty when nothing is configured.
|
|
29
|
-
if (!ageCheckActive && !trustCheckActive)
|
|
30
|
-
return undefined;
|
|
31
31
|
const cutoff = ageCheckActive
|
|
32
32
|
? (opts.now ?? Date.now()) - opts.minimumReleaseAge * 60 * 1000
|
|
33
33
|
: 0;
|
|
@@ -84,20 +84,37 @@ export function createNpmResolutionVerifier(opts) {
|
|
|
84
84
|
const minimumReleaseAge = opts.minimumReleaseAge ?? 0;
|
|
85
85
|
const trustPolicy = opts.trustPolicy;
|
|
86
86
|
const trustPolicyIgnoreAfter = opts.trustPolicyIgnoreAfter;
|
|
87
|
-
const verify = async (resolution, { name, version }) => {
|
|
87
|
+
const verify = async (resolution, { name, version, nonSemverVersion }) => {
|
|
88
88
|
if (!isNpmRegistryResolution(resolution))
|
|
89
89
|
return { ok: true };
|
|
90
|
-
//
|
|
91
|
-
//
|
|
90
|
+
// URL/git-keyed entries are deliberate non-registry deps. They can still
|
|
91
|
+
// carry a semver `version` copied from the resolved manifest, so the
|
|
92
|
+
// semver guard below isn't enough on its own — the registry policies and
|
|
93
|
+
// the tarball-URL binding don't apply to them, and a registry lookup
|
|
92
94
|
// would 404.
|
|
95
|
+
if (nonSemverVersion != null)
|
|
96
|
+
return { ok: true };
|
|
93
97
|
if (!semver.valid(version))
|
|
94
98
|
return { ok: true };
|
|
99
|
+
const tarballUrl = resolution.tarball;
|
|
100
|
+
const registry = pickRegistryForVersion(opts.registries, namedRegistryPrefixes, name, tarballUrl);
|
|
101
|
+
// A registry entry that pins an explicit tarball URL must point at the
|
|
102
|
+
// artifact the registry's own metadata lists. Otherwise a trusted
|
|
103
|
+
// `name@version` could front bytes from an attacker-chosen URL (with a
|
|
104
|
+
// matching integrity for those bytes). This binding is unconditional —
|
|
105
|
+
// it does not depend on `minimumReleaseAge`/`trustPolicy` and isn't
|
|
106
|
+
// narrowed by their exclude lists, since it guards integrity rather
|
|
107
|
+
// than maturity/trust. Registry entries with no tarball URL reconstruct
|
|
108
|
+
// it from name+version+registry, so they're inherently bound.
|
|
109
|
+
if (typeof tarballUrl === 'string') {
|
|
110
|
+
const urlViolation = await runTarballUrlCheck(lookupContext, registry, name, version, tarballUrl);
|
|
111
|
+
if (urlViolation)
|
|
112
|
+
return urlViolation;
|
|
113
|
+
}
|
|
95
114
|
const ageApplies = ageCheckActive && !isExcluded(excludePolicy, name, version);
|
|
96
115
|
const trustApplies = trustCheckActive && !isExcluded(trustExcludePolicy, name, version);
|
|
97
116
|
if (!ageApplies && !trustApplies)
|
|
98
117
|
return { ok: true };
|
|
99
|
-
const tarballUrl = resolution.tarball;
|
|
100
|
-
const registry = pickRegistryForVersion(opts.registries, namedRegistryPrefixes, name, tarballUrl);
|
|
101
118
|
if (ageApplies) {
|
|
102
119
|
const ageViolation = await runAgeCheck(lookupContext, registry, name, version, cutoff, opts.ignoreMissingTimeField === true);
|
|
103
120
|
if (ageViolation)
|
|
@@ -127,6 +144,12 @@ export function createNpmResolutionVerifier(opts) {
|
|
|
127
144
|
return {
|
|
128
145
|
verify,
|
|
129
146
|
policy: {
|
|
147
|
+
// Marks runs that enforced the tarball-URL binding. A cache record
|
|
148
|
+
// written before this rule existed lacks the flag, so
|
|
149
|
+
// `canTrustPastCheck` rejects it and forces a re-verification that
|
|
150
|
+
// applies the binding — otherwise an upgrade could keep trusting a
|
|
151
|
+
// lockfile that was only ever age/trust-checked.
|
|
152
|
+
tarballUrlBinding: true,
|
|
130
153
|
minimumReleaseAge,
|
|
131
154
|
minimumReleaseAgeExclude: sortedMinAgeExcludes,
|
|
132
155
|
trustPolicy: trustPolicy ?? null,
|
|
@@ -134,6 +157,10 @@ export function createNpmResolutionVerifier(opts) {
|
|
|
134
157
|
trustPolicyIgnoreAfter: trustPolicyIgnoreAfter ?? null,
|
|
135
158
|
},
|
|
136
159
|
canTrustPastCheck: (cached) => {
|
|
160
|
+
// The tarball-URL binding is unconditional today; a cached run that
|
|
161
|
+
// didn't record it can't be trusted to have enforced it.
|
|
162
|
+
if (cached.tarballUrlBinding !== true)
|
|
163
|
+
return false;
|
|
137
164
|
// Maturity: a previously cached run under a larger cutoff
|
|
138
165
|
// (stricter window) is trustworthy under a smaller current one —
|
|
139
166
|
// its set of accepted versions is a subset of today's. The
|
|
@@ -223,6 +250,44 @@ async function runAgeCheck(context, registry, name, version, cutoff, ignoreMissi
|
|
|
223
250
|
}
|
|
224
251
|
return undefined;
|
|
225
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Confirm the lockfile-pinned tarball URL is the artifact the registry's
|
|
255
|
+
* own metadata lists for this exact `name@version`.
|
|
256
|
+
*
|
|
257
|
+
* Fail-closed: the entry passes only when the registry metadata
|
|
258
|
+
* affirmatively lists this version with a matching tarball URL. If the
|
|
259
|
+
* metadata can't be fetched, doesn't list the version, or omits
|
|
260
|
+
* `dist.tarball`, the entry can't be confirmed and is rejected — otherwise
|
|
261
|
+
* a tampered lockfile could smuggle a malicious URL past the check by
|
|
262
|
+
* pointing it at a `name@version` the registry can't vouch for.
|
|
263
|
+
*/
|
|
264
|
+
async function runTarballUrlCheck(context, registry, name, version, lockfileTarball) {
|
|
265
|
+
const meta = await fetchAbbreviatedMeta(context, registry, name);
|
|
266
|
+
const registryTarball = meta?.versionTarballs?.get(version);
|
|
267
|
+
if (registryTarball != null && sameTarballUrl(lockfileTarball, registryTarball)) {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
ok: false,
|
|
272
|
+
code: TARBALL_URL_MISMATCH_VIOLATION_CODE,
|
|
273
|
+
reason: registryTarball == null
|
|
274
|
+
? "could not be verified against the registry's published metadata"
|
|
275
|
+
: `has a tarball URL (${lockfileTarball}) that does not match the registry's published metadata (${registryTarball})`,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function sameTarballUrl(a, b) {
|
|
279
|
+
return canonicalTarballUrl(a) === canonicalTarballUrl(b);
|
|
280
|
+
}
|
|
281
|
+
// Mirror the tolerance toLockfileResolution applies when it decides whether
|
|
282
|
+
// a tarball URL is "the expected one": ignore the protocol and `%2f` scope
|
|
283
|
+
// encoding so a benign http/https or encoding difference isn't read as
|
|
284
|
+
// tampering. The `%2f` match is case-insensitive because `normalizeRegistryUrl`
|
|
285
|
+
// (`new URL().toString()`) can upper-case percent-escapes to `%2F`.
|
|
286
|
+
function canonicalTarballUrl(url) {
|
|
287
|
+
const normalized = normalizeRegistryUrl(url).replace(/%2f/gi, '/');
|
|
288
|
+
const schemeEnd = normalized.indexOf('://');
|
|
289
|
+
return schemeEnd === -1 ? normalized : normalized.slice(schemeEnd + 3);
|
|
290
|
+
}
|
|
226
291
|
/**
|
|
227
292
|
* Run the resolver-time `failIfTrustDowngraded` check against the
|
|
228
293
|
* pinned lockfile version. The packument is fetched through a
|
|
@@ -341,12 +406,23 @@ function projectTrustManifest(manifest) {
|
|
|
341
406
|
// reads them; cast away the unsoundness so callers see the same nominal
|
|
342
407
|
// shape without the per-version dependency graph / scripts / README bulk
|
|
343
408
|
// carrying through. `_npmUser` is similarly narrowed to just
|
|
344
|
-
// `trustedPublisher` — the only sub-
|
|
345
|
-
// we don't keep maintainer name/email PII resident in the
|
|
409
|
+
// `trustedPublisher` and `approver` — the only sub-fields the trust check
|
|
410
|
+
// inspects — so we don't keep maintainer name/email PII resident in the
|
|
411
|
+
// cache.
|
|
412
|
+
const approver = manifest._npmUser?.approver;
|
|
346
413
|
const trustedPublisher = manifest._npmUser?.trustedPublisher;
|
|
347
414
|
const provenance = manifest.dist?.attestations?.provenance;
|
|
415
|
+
let npmUser = undefined;
|
|
416
|
+
if (approver) {
|
|
417
|
+
npmUser ||= {};
|
|
418
|
+
npmUser.approver = {};
|
|
419
|
+
}
|
|
420
|
+
if (trustedPublisher) {
|
|
421
|
+
npmUser ||= {};
|
|
422
|
+
npmUser.trustedPublisher = trustedPublisher;
|
|
423
|
+
}
|
|
348
424
|
return {
|
|
349
|
-
_npmUser:
|
|
425
|
+
_npmUser: npmUser,
|
|
350
426
|
dist: provenance != null
|
|
351
427
|
? { attestations: { provenance } }
|
|
352
428
|
: undefined,
|
|
@@ -429,7 +505,7 @@ async function tryAbbreviatedModifiedShortcut(context, registry, name, version)
|
|
|
429
505
|
// publish time — but only for versions the registry currently lists.
|
|
430
506
|
// An unpublished or never-published pin would otherwise pass the gate
|
|
431
507
|
// on a stale package-level timestamp.
|
|
432
|
-
if (!meta?.
|
|
508
|
+
if (!meta?.versionTarballs?.has(version))
|
|
433
509
|
return undefined;
|
|
434
510
|
return modified;
|
|
435
511
|
}
|
|
@@ -492,18 +568,26 @@ function validateSharedMeta(meta, name) {
|
|
|
492
568
|
return undefined;
|
|
493
569
|
return meta;
|
|
494
570
|
}
|
|
495
|
-
// Project the abbreviated packument down to the
|
|
496
|
-
// actually reads — package-level `modified
|
|
497
|
-
//
|
|
571
|
+
// Project the abbreviated packument down to the few fields the verifier
|
|
572
|
+
// actually reads — package-level `modified`, plus a per-version map of
|
|
573
|
+
// `dist.tarball` (whose keys double as the version-existence set for the
|
|
574
|
+
// `tryAbbreviatedModifiedShortcut` check and the tarball-URL binding). The
|
|
498
575
|
// resolver populates the abbreviated mirror with every version's
|
|
499
576
|
// dependency / engine / dist info, which can run to hundreds of KB per
|
|
500
577
|
// package and accumulate to many GB across a multi-thousand-entry
|
|
501
578
|
// lockfile (see #11860). The full document is GC-able as soon as this
|
|
502
|
-
// closure returns.
|
|
579
|
+
// closure returns; only the short tarball-URL strings are retained.
|
|
503
580
|
function projectAbbreviatedMeta(meta) {
|
|
581
|
+
let versionTarballs;
|
|
582
|
+
if (meta.versions) {
|
|
583
|
+
versionTarballs = new Map();
|
|
584
|
+
for (const [version, manifest] of Object.entries(meta.versions)) {
|
|
585
|
+
versionTarballs.set(version, manifest.dist?.tarball);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
504
588
|
return {
|
|
505
589
|
modified: meta.modified,
|
|
506
|
-
|
|
590
|
+
versionTarballs,
|
|
507
591
|
};
|
|
508
592
|
}
|
|
509
593
|
function readLocalMetaTime(context, registry, name) {
|
|
@@ -542,12 +626,14 @@ function pickRegistryForVersion(registries, namedRegistryPrefixes, name, tarball
|
|
|
542
626
|
// origin we'd otherwise miss. Match the longest prefix so that two named
|
|
543
627
|
// registries sharing a host but differing by path don't collide.
|
|
544
628
|
if (tarballUrl) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
629
|
+
// Match on the same canonical form the tarball comparison uses, so a
|
|
630
|
+
// named-registry tarball that differs from the configured base only by
|
|
631
|
+
// scheme or `%2f` encoding still routes to its registry instead of
|
|
632
|
+
// falling back (and then failing closed against the wrong packument).
|
|
633
|
+
const normalized = canonicalTarballUrl(tarballUrl);
|
|
634
|
+
for (const prefix of namedRegistryPrefixes) {
|
|
635
|
+
if (normalized.startsWith(canonicalTarballUrl(prefix)))
|
|
636
|
+
return prefix;
|
|
551
637
|
}
|
|
552
638
|
}
|
|
553
639
|
return pickRegistryForPackage(registries, name);
|
|
@@ -597,6 +683,14 @@ function isNpmRegistryResolution(resolution) {
|
|
|
597
683
|
// the resolver and aren't subject to release-age policy.
|
|
598
684
|
if ('gitHosted' in resolution && resolution.gitHosted)
|
|
599
685
|
return false;
|
|
686
|
+
const tarball = resolution.tarball;
|
|
687
|
+
if (typeof tarball === 'string') {
|
|
688
|
+
// Local/non-registry tarballs (for example `file:`) have no packument
|
|
689
|
+
// metadata, so minimumReleaseAge/trustPolicy verification cannot apply.
|
|
690
|
+
const protocol = tryParseUrl(tarball)?.protocol;
|
|
691
|
+
if (protocol != null && protocol !== 'http:' && protocol !== 'https:')
|
|
692
|
+
return false;
|
|
693
|
+
}
|
|
600
694
|
return 'tarball' in resolution || 'integrity' in resolution;
|
|
601
695
|
}
|
|
602
696
|
//# sourceMappingURL=createNpmResolutionVerifier.js.map
|
package/lib/pickPackage.js
CHANGED
|
@@ -201,7 +201,7 @@ export async function pickPackage(ctx, spec, opts) {
|
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
|
-
if (opts.publishedBy) {
|
|
204
|
+
if (opts.publishedBy && opts.publishedByExclude?.(spec.name) !== true) {
|
|
205
205
|
const mtime = await limit(async () => getFileMtime(pkgMirror));
|
|
206
206
|
if (mtime != null && mtime >= opts.publishedBy) {
|
|
207
207
|
metaCachedInStore = metaCachedInStore ?? await limit(async () => loadMeta(pkgMirror));
|
package/lib/trustChecks.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PackageInRegistry, PackageMeta } from '@pnpm/resolving.registry.types';
|
|
2
2
|
import type { PackageVersionPolicy } from '@pnpm/types';
|
|
3
|
-
type TrustEvidence = 'provenance' | 'trustedPublisher';
|
|
3
|
+
type TrustEvidence = 'provenance' | 'trustedPublisher' | 'stagedPublish';
|
|
4
4
|
export declare function failIfTrustDowngraded(meta: PackageMeta, version: string, opts?: {
|
|
5
5
|
trustPolicyExclude?: PackageVersionPolicy;
|
|
6
6
|
trustPolicyIgnoreAfter?: number;
|
package/lib/trustChecks.js
CHANGED
|
@@ -2,6 +2,7 @@ import { PnpmError } from '@pnpm/error';
|
|
|
2
2
|
import semver from 'semver';
|
|
3
3
|
import { assertMetaHasTime } from './pickPackageFromMeta.js';
|
|
4
4
|
const TRUST_RANK = {
|
|
5
|
+
stagedPublish: 3,
|
|
5
6
|
trustedPublisher: 2,
|
|
6
7
|
provenance: 1,
|
|
7
8
|
};
|
|
@@ -51,6 +52,7 @@ export function failIfTrustDowngraded(meta, version, opts) {
|
|
|
51
52
|
}
|
|
52
53
|
function prettyPrintTrustEvidence(trustEvidence) {
|
|
53
54
|
switch (trustEvidence) {
|
|
55
|
+
case 'stagedPublish': return 'staged publish';
|
|
54
56
|
case 'trustedPublisher': return 'trusted publisher';
|
|
55
57
|
case 'provenance': return 'provenance attestation';
|
|
56
58
|
default: return 'no trust evidence';
|
|
@@ -70,14 +72,19 @@ function detectStrongestTrustEvidenceBeforeDate(meta, beforeDate, options) {
|
|
|
70
72
|
const trustEvidence = getTrustEvidence(manifest);
|
|
71
73
|
if (!trustEvidence)
|
|
72
74
|
continue;
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
+
if (best === undefined || TRUST_RANK[trustEvidence] > TRUST_RANK[best]) {
|
|
76
|
+
best = trustEvidence;
|
|
77
|
+
if (best === 'stagedPublish') {
|
|
78
|
+
return best;
|
|
79
|
+
}
|
|
75
80
|
}
|
|
76
|
-
best ||= 'provenance';
|
|
77
81
|
}
|
|
78
82
|
return best;
|
|
79
83
|
}
|
|
80
84
|
export function getTrustEvidence(manifest) {
|
|
85
|
+
if (manifest._npmUser?.approver) {
|
|
86
|
+
return 'stagedPublish';
|
|
87
|
+
}
|
|
81
88
|
if (manifest._npmUser?.trustedPublisher && manifest.dist?.attestations?.provenance) {
|
|
82
89
|
return 'trustedPublisher';
|
|
83
90
|
}
|
package/lib/violationCodes.d.ts
CHANGED
package/lib/violationCodes.js
CHANGED
|
@@ -10,4 +10,5 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export const MINIMUM_RELEASE_AGE_VIOLATION_CODE = 'MINIMUM_RELEASE_AGE_VIOLATION';
|
|
12
12
|
export const TRUST_DOWNGRADE_VIOLATION_CODE = 'TRUST_DOWNGRADE';
|
|
13
|
+
export const TARBALL_URL_MISMATCH_VIOLATION_CODE = 'TARBALL_URL_MISMATCH';
|
|
13
14
|
//# sourceMappingURL=violationCodes.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/resolving.npm-resolver",
|
|
3
|
-
"version": "1101.
|
|
3
|
+
"version": "1101.5.0",
|
|
4
4
|
"description": "Resolver for npm-hosted packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
],
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"funding": "https://opencollective.com/pnpm",
|
|
13
|
-
"repository":
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/pnpm/pnpm/tree/main/resolving/npm-resolver"
|
|
16
|
+
},
|
|
14
17
|
"homepage": "https://github.com/pnpm/pnpm/tree/main/resolving/npm-resolver#readme",
|
|
15
18
|
"bugs": {
|
|
16
19
|
"url": "https://github.com/pnpm/pnpm/issues"
|
|
@@ -40,27 +43,27 @@
|
|
|
40
43
|
"semver-utils": "^1.1.4",
|
|
41
44
|
"ssri": "13.0.1",
|
|
42
45
|
"version-selector-type": "^3.0.0",
|
|
43
|
-
"@pnpm/config.pick-registry-for-package": "1100.0.
|
|
44
|
-
"@pnpm/
|
|
45
|
-
"@pnpm/core-loggers": "1100.1.2",
|
|
46
|
+
"@pnpm/config.pick-registry-for-package": "1100.0.7",
|
|
47
|
+
"@pnpm/config.version-policy": "1100.1.3",
|
|
46
48
|
"@pnpm/crypto.hash": "1100.0.1",
|
|
47
|
-
"@pnpm/config.version-policy": "1100.1.2",
|
|
48
|
-
"@pnpm/error": "1100.0.0",
|
|
49
|
-
"@pnpm/fetching.types": "1100.0.1",
|
|
50
|
-
"@pnpm/resolving.registry.pkg-metadata-filter": "1100.0.5",
|
|
51
|
-
"@pnpm/resolving.registry.types": "1100.0.5",
|
|
52
|
-
"@pnpm/resolving.resolver-base": "1100.3.1",
|
|
53
|
-
"@pnpm/store.cafs": "1100.1.7",
|
|
54
|
-
"@pnpm/store.index": "1100.1.0",
|
|
55
49
|
"@pnpm/fs.graceful-fs": "1100.1.0",
|
|
56
|
-
"@pnpm/types": "1101.2.0",
|
|
57
|
-
"@pnpm/workspace.range-resolver": "1100.0.1",
|
|
58
50
|
"@pnpm/resolving.jsr-specifier-parser": "1100.0.0",
|
|
51
|
+
"@pnpm/constants": "1100.0.0",
|
|
52
|
+
"@pnpm/resolving.registry.types": "1100.1.1",
|
|
53
|
+
"@pnpm/resolving.resolver-base": "1100.4.0",
|
|
54
|
+
"@pnpm/store.cafs": "1100.1.8",
|
|
55
|
+
"@pnpm/store.index": "1100.1.0",
|
|
56
|
+
"@pnpm/resolving.registry.pkg-metadata-filter": "1100.0.7",
|
|
57
|
+
"@pnpm/core-loggers": "1100.1.3",
|
|
58
|
+
"@pnpm/types": "1101.3.0",
|
|
59
|
+
"@pnpm/fetching.types": "1100.0.1",
|
|
60
|
+
"@pnpm/workspace.range-resolver": "1100.0.1",
|
|
61
|
+
"@pnpm/error": "1100.0.0",
|
|
59
62
|
"@pnpm/workspace.spec-parser": "1100.0.0"
|
|
60
63
|
},
|
|
61
64
|
"peerDependencies": {
|
|
62
65
|
"@pnpm/logger": "^1001.0.1",
|
|
63
|
-
"@pnpm/worker": "^1100.1.
|
|
66
|
+
"@pnpm/worker": "^1100.1.9"
|
|
64
67
|
},
|
|
65
68
|
"devDependencies": {
|
|
66
69
|
"@jest/globals": "30.3.0",
|
|
@@ -70,11 +73,11 @@
|
|
|
70
73
|
"@types/ssri": "^7.1.5",
|
|
71
74
|
"load-json-file": "^7.0.1",
|
|
72
75
|
"tempy": "3.0.0",
|
|
73
|
-
"@pnpm/
|
|
74
|
-
"@pnpm/
|
|
75
|
-
"@pnpm/resolving.npm-resolver": "1101.3.3",
|
|
76
|
+
"@pnpm/network.fetch": "1100.1.0",
|
|
77
|
+
"@pnpm/resolving.npm-resolver": "1101.5.0",
|
|
76
78
|
"@pnpm/test-fixtures": "1100.0.0",
|
|
77
|
-
"@pnpm/
|
|
79
|
+
"@pnpm/testing.mock-agent": "1101.0.0",
|
|
80
|
+
"@pnpm/logger": "1100.0.0"
|
|
78
81
|
},
|
|
79
82
|
"engines": {
|
|
80
83
|
"node": ">=22.13"
|