@vltpkg/package-info 1.0.0-rc.32 → 1.0.0-rc.33
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/dist/index.d.ts +9 -0
- package/dist/index.js +58 -44
- package/package.json +21 -14
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,15 @@ export type PackageInfoClientOptions = RegistryClientOptions & SpecOptions & {
|
|
|
28
28
|
export type PackageInfoClientRequestOptions = PickManifestOptions & RegistryClientRequestOptions & {
|
|
29
29
|
/** dir to resolve `file://` specifiers against. Defaults to projectRoot. */
|
|
30
30
|
from?: string;
|
|
31
|
+
/**
|
|
32
|
+
* When true, requests the full packument document from the registry
|
|
33
|
+
* instead of the abbreviated "corgi" format. Use this when you need
|
|
34
|
+
* fields like `time`, `maintainers`, or `_rev` that are stripped
|
|
35
|
+
* from the abbreviated response.
|
|
36
|
+
*
|
|
37
|
+
* Defaults to `false` (abbreviated packument for faster installs).
|
|
38
|
+
*/
|
|
39
|
+
fullPackument?: boolean;
|
|
31
40
|
};
|
|
32
41
|
export type PackageInfoClientExtractOptions = PackageInfoClientRequestOptions & {
|
|
33
42
|
integrity?: Integrity;
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,13 @@ const xdg = new XDG('vlt');
|
|
|
18
18
|
export const delimiter = '~';
|
|
19
19
|
// the maximum duration of a manifest cache file
|
|
20
20
|
const manifestCacheMaxAge = 5 * 60 * 1000;
|
|
21
|
+
/**
|
|
22
|
+
* There is no default registry. Anything that needs to build a registry
|
|
23
|
+
* URL fails with a `ECONFIG` error when none has been configured.
|
|
24
|
+
*/
|
|
25
|
+
const noRegistryError = (spec) => error('No registry configured to resolve this spec. Set "registry" in ' +
|
|
26
|
+
'vlt.json, pass --registry, or run `vlt login --registry=<url>`. ' +
|
|
27
|
+
'See https://docs.vlt.sh/cli', { code: 'ECONFIG', spec });
|
|
21
28
|
export class PackageInfoClient {
|
|
22
29
|
#registryClient;
|
|
23
30
|
#projectRoot;
|
|
@@ -29,6 +36,7 @@ export class PackageInfoClient {
|
|
|
29
36
|
#trustedIntegrities = new Map();
|
|
30
37
|
#manifestCacheMinAge = Date.now() - manifestCacheMaxAge;
|
|
31
38
|
#cachePath;
|
|
39
|
+
#packumentPromises = new Map();
|
|
32
40
|
get registryClient() {
|
|
33
41
|
if (!this.#registryClient) {
|
|
34
42
|
this.#registryClient = new RegistryClient(this.options);
|
|
@@ -109,7 +117,10 @@ export class PackageInfoClient {
|
|
|
109
117
|
...(useCache === false ? { useCache } : {}),
|
|
110
118
|
});
|
|
111
119
|
if (response.statusCode !== 200) {
|
|
112
|
-
throw this.#resolveError(spec, options,
|
|
120
|
+
throw this.#resolveError(spec, options, `Registry returned HTTP ${response.statusCode} when ` +
|
|
121
|
+
`fetching the tarball for ${spec}. The resolved version ` +
|
|
122
|
+
`may have been unpublished, or the registry may be ` +
|
|
123
|
+
`misconfigured or unreachable.`, {
|
|
113
124
|
url: r.resolved,
|
|
114
125
|
response,
|
|
115
126
|
});
|
|
@@ -272,7 +283,7 @@ export class PackageInfoClient {
|
|
|
272
283
|
if (options.arch) {
|
|
273
284
|
extra += `${delimiter}arch:${options.arch}`;
|
|
274
285
|
}
|
|
275
|
-
return encodeURIComponent(`${spec.registry}${delimiter}${spec}${extra}`);
|
|
286
|
+
return encodeURIComponent(`${spec.registry ?? ''}${delimiter}${spec}${extra}`);
|
|
276
287
|
}
|
|
277
288
|
/**
|
|
278
289
|
* Conditionally return the path to the manifest cache file. The logic
|
|
@@ -293,30 +304,6 @@ export class PackageInfoClient {
|
|
|
293
304
|
const key = this.#manifestCacheKey(f, options);
|
|
294
305
|
return pathResolve(this.#cachePath, 'package-info', key);
|
|
295
306
|
}
|
|
296
|
-
async #registryManifestRequest(spec, options) {
|
|
297
|
-
const { registry, name, registrySpec } = spec.final;
|
|
298
|
-
/* c8 ignore start */
|
|
299
|
-
if (!spec.range?.isSingle || !registrySpec) {
|
|
300
|
-
throw this.#resolveError(spec, options, 'failed to request manifest', { spec });
|
|
301
|
-
}
|
|
302
|
-
/* c8 ignore stop */
|
|
303
|
-
const possibleLeadingChars = ['=', '^', '~', 'v'];
|
|
304
|
-
const hasLeadingRange = possibleLeadingChars.some(char => registrySpec.startsWith(char));
|
|
305
|
-
const version = hasLeadingRange ? registrySpec.slice(1) : registrySpec;
|
|
306
|
-
const pakuURL = new URL(`${name}/${version}`, registry);
|
|
307
|
-
const response = await this.registryClient.request(pakuURL, {
|
|
308
|
-
headers: {
|
|
309
|
-
accept: 'application/json',
|
|
310
|
-
},
|
|
311
|
-
});
|
|
312
|
-
if (response.statusCode !== 200) {
|
|
313
|
-
throw this.#resolveError(spec, options, 'failed to fetch manifest', {
|
|
314
|
-
url: pakuURL,
|
|
315
|
-
response,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
return response.json();
|
|
319
|
-
}
|
|
320
307
|
async tarball(spec, options = {}) {
|
|
321
308
|
if (typeof spec === 'string')
|
|
322
309
|
spec = Spec.parse(spec, this.options);
|
|
@@ -325,10 +312,14 @@ export class PackageInfoClient {
|
|
|
325
312
|
case 'registry': {
|
|
326
313
|
const { dist } = await this.manifest(spec, options);
|
|
327
314
|
if (!dist)
|
|
328
|
-
throw this.#resolveError(spec, options,
|
|
315
|
+
throw this.#resolveError(spec, options, `The registry manifest for ${spec} has no "dist" section, ` +
|
|
316
|
+
`so no tarball can be resolved. The package version may be ` +
|
|
317
|
+
`malformed or unpublished.`);
|
|
329
318
|
const { tarball, integrity } = dist;
|
|
330
319
|
if (!tarball) {
|
|
331
|
-
throw this.#resolveError(spec, options,
|
|
320
|
+
throw this.#resolveError(spec, options, `The registry manifest for ${spec} is missing a tarball URL ` +
|
|
321
|
+
`(dist.tarball). The package version may be malformed or ` +
|
|
322
|
+
`unpublished in this registry.`);
|
|
332
323
|
}
|
|
333
324
|
const fetchTarball = async (useCache) => {
|
|
334
325
|
const trustIntegrity = this.#trustedIntegrities.get(tarball) === integrity;
|
|
@@ -339,7 +330,10 @@ export class PackageInfoClient {
|
|
|
339
330
|
...(useCache === false ? { useCache } : {}),
|
|
340
331
|
});
|
|
341
332
|
if (response.statusCode !== 200) {
|
|
342
|
-
throw this.#resolveError(spec, options,
|
|
333
|
+
throw this.#resolveError(spec, options, `Registry returned HTTP ${response.statusCode} when ` +
|
|
334
|
+
`fetching the tarball for ${spec} at ${tarball}. The ` +
|
|
335
|
+
`version may have been unpublished, or the registry may ` +
|
|
336
|
+
`be misconfigured or unreachable.`, { response, url: tarball });
|
|
343
337
|
}
|
|
344
338
|
// if we don't already trust it, but it's valid, start
|
|
345
339
|
// trusting it
|
|
@@ -474,9 +468,7 @@ export class PackageInfoClient {
|
|
|
474
468
|
// Cache miss, fetch from packument
|
|
475
469
|
}
|
|
476
470
|
}
|
|
477
|
-
const mani =
|
|
478
|
-
await this.#registryManifestRequest(spec, options)
|
|
479
|
-
: pickManifest(await this.packument(f, options), spec, options);
|
|
471
|
+
const mani = pickManifest(await this.packument(f, options), spec, options);
|
|
480
472
|
if (!mani)
|
|
481
473
|
throw this.#resolveError(spec, options);
|
|
482
474
|
// Cache the manifest data
|
|
@@ -606,22 +598,44 @@ export class PackageInfoClient {
|
|
|
606
598
|
}
|
|
607
599
|
case 'registry': {
|
|
608
600
|
const { registry, name } = f;
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
throw this.#resolveError(spec, options, 'failed to fetch packument', {
|
|
617
|
-
url: pakuURL,
|
|
618
|
-
response,
|
|
619
|
-
});
|
|
601
|
+
if (!registry)
|
|
602
|
+
throw noRegistryError(spec);
|
|
603
|
+
// Full packument requests bypass coalescing since they
|
|
604
|
+
// return different data than the abbreviated format.
|
|
605
|
+
if (options.fullPackument) {
|
|
606
|
+
const pakuURL = new URL(name, registry);
|
|
607
|
+
return this.#fetchPackument(spec, options, pakuURL);
|
|
620
608
|
}
|
|
621
|
-
|
|
609
|
+
const packumentKey = `${registry}${name}`;
|
|
610
|
+
const inflight = this.#packumentPromises.get(packumentKey);
|
|
611
|
+
if (inflight)
|
|
612
|
+
return inflight;
|
|
613
|
+
const pakuURL = new URL(name, registry);
|
|
614
|
+
const promise = this.#fetchPackument(spec, options, pakuURL);
|
|
615
|
+
this.#packumentPromises.set(packumentKey, promise);
|
|
616
|
+
// Clean up once settled so we don't leak memory.
|
|
617
|
+
// Use .then/.catch instead of .finally to avoid creating
|
|
618
|
+
// an unhandled rejection from the derived promise.
|
|
619
|
+
promise.then(() => this.#packumentPromises.delete(packumentKey), () => this.#packumentPromises.delete(packumentKey));
|
|
620
|
+
return promise;
|
|
622
621
|
}
|
|
623
622
|
}
|
|
624
623
|
}
|
|
624
|
+
async #fetchPackument(spec, options, pakuURL) {
|
|
625
|
+
const accept = options.fullPackument ?
|
|
626
|
+
'application/json'
|
|
627
|
+
: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*';
|
|
628
|
+
const response = await this.registryClient.request(pakuURL, {
|
|
629
|
+
headers: { accept },
|
|
630
|
+
});
|
|
631
|
+
if (response.statusCode !== 200) {
|
|
632
|
+
throw this.#resolveError(spec, options, 'failed to fetch packument', {
|
|
633
|
+
url: pakuURL,
|
|
634
|
+
response,
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
return response.json();
|
|
638
|
+
}
|
|
625
639
|
async resolve(spec, options = {}) {
|
|
626
640
|
const memoKey = String(spec);
|
|
627
641
|
if (typeof spec === 'string')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vltpkg/package-info",
|
|
3
3
|
"description": "Resolve and fetch package metadata and tarballs",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.33",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/vltpkg/vltpkg.git",
|
|
@@ -13,16 +13,16 @@
|
|
|
13
13
|
"url": "http://vlt.sh"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@vltpkg/error-cause": "1.0.0-rc.
|
|
17
|
-
"@vltpkg/git": "1.0.0-rc.
|
|
18
|
-
"@vltpkg/package-json": "1.0.0-rc.
|
|
19
|
-
"@vltpkg/pick-manifest": "1.0.0-rc.
|
|
20
|
-
"@vltpkg/registry-client": "1.0.0-rc.
|
|
21
|
-
"@vltpkg/spec": "1.0.0-rc.
|
|
22
|
-
"@vltpkg/tar": "1.0.0-rc.
|
|
23
|
-
"@vltpkg/types": "1.0.0-rc.
|
|
24
|
-
"@vltpkg/workspaces": "1.0.0-rc.
|
|
25
|
-
"@vltpkg/xdg": "1.0.0-rc.
|
|
16
|
+
"@vltpkg/error-cause": "1.0.0-rc.33",
|
|
17
|
+
"@vltpkg/git": "1.0.0-rc.33",
|
|
18
|
+
"@vltpkg/package-json": "1.0.0-rc.33",
|
|
19
|
+
"@vltpkg/pick-manifest": "1.0.0-rc.33",
|
|
20
|
+
"@vltpkg/registry-client": "1.0.0-rc.33",
|
|
21
|
+
"@vltpkg/spec": "1.0.0-rc.33",
|
|
22
|
+
"@vltpkg/tar": "1.0.0-rc.33",
|
|
23
|
+
"@vltpkg/types": "1.0.0-rc.33",
|
|
24
|
+
"@vltpkg/workspaces": "1.0.0-rc.33",
|
|
25
|
+
"@vltpkg/xdg": "1.0.0-rc.33",
|
|
26
26
|
"ssri": "^13.0.0",
|
|
27
27
|
"tar": "^7.5.2"
|
|
28
28
|
},
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"@types/node": "^22.19.2",
|
|
32
32
|
"@types/pacote": "^11.1.8",
|
|
33
33
|
"@vltpkg/benchmark": "0.0.0",
|
|
34
|
-
"@vltpkg/cache-unzip": "1.0.0-rc.
|
|
35
|
-
"@vltpkg/vlt-json": "1.0.0-rc.
|
|
34
|
+
"@vltpkg/cache-unzip": "1.0.0-rc.33",
|
|
35
|
+
"@vltpkg/vlt-json": "1.0.0-rc.33",
|
|
36
36
|
"eslint": "^9.39.1",
|
|
37
37
|
"pacote": "^21.0.4",
|
|
38
38
|
"prettier": "^3.7.4",
|
|
@@ -73,5 +73,12 @@
|
|
|
73
73
|
},
|
|
74
74
|
"files": [
|
|
75
75
|
"dist"
|
|
76
|
-
]
|
|
76
|
+
],
|
|
77
|
+
"bugs": [
|
|
78
|
+
{
|
|
79
|
+
"type": "link",
|
|
80
|
+
"url": "https://github.com/vltpkg/vltpkg/issues"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"homepage": "https://github.com/vltpkg/vltpkg/tree/main/src/package-info#readme"
|
|
77
84
|
}
|