@vltpkg/cli-js 1.1.1 → 1.2.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/{access-YYMAAPHV.js → access-FTHPFPUJ.js} +8 -8
- package/{bugs-RK5JBPSC.js → bugs-QS6HQUO2.js} +17 -17
- package/{build-DVJSYCNF.js → build-H27SXMAS.js} +11 -11
- package/{cache-JKQNGZ7L.js → cache-IB4HMFDT.js} +143 -14
- package/cache-unzip-src-unzip.js +2934 -164
- package/{chunk-BWEH7DHQ.js → chunk-3CUFJPBK.js} +1 -1
- package/{chunk-CBASIDQH.js → chunk-55DYW2MP.js} +1 -1
- package/{chunk-6FT6K5YN.js → chunk-5BD4QGW2.js} +25 -7
- package/{chunk-WE2TQN32.js → chunk-5PP77V44.js} +2 -2
- package/{chunk-LN2A74PF.js → chunk-5YB6UIC3.js} +247 -37
- package/{chunk-CEHPRPGQ.js → chunk-6A3XS52F.js} +33 -0
- package/{chunk-X2AWQGYG.js → chunk-6G7MTZGS.js} +6 -6
- package/{chunk-V4YCZZHY.js → chunk-7KFMQ3BR.js} +16 -8
- package/{chunk-JZJWASXL.js → chunk-B2FK2HHL.js} +79 -58
- package/{chunk-DF5K4CYR.js → chunk-FOJCK57G.js} +5 -5
- package/{chunk-GDT6KI4I.js → chunk-FSZF2RSQ.js} +4 -4
- package/{chunk-VFBCWAOC.js → chunk-G5BSQ6DP.js} +7 -0
- package/{chunk-XKVU23NC.js → chunk-G5NJ7CYI.js} +1 -1
- package/{chunk-34TE4HZS.js → chunk-GUATFMMU.js} +2 -2
- package/{chunk-YBVTY6ZW.js → chunk-JTUZP2OD.js} +1 -1
- package/{chunk-MZA6N2TA.js → chunk-LD4BQJBG.js} +4 -4
- package/{chunk-KDF7PEBY.js → chunk-LEGPLJWK.js} +5 -5
- package/{chunk-XIF734VO.js → chunk-LKQ5R4VX.js} +4 -4
- package/{chunk-DR4Z63B6.js → chunk-NJZSCUD4.js} +3 -3
- package/{chunk-2PWSMJD7.js → chunk-O44Z6MAV.js} +1 -1
- package/{chunk-DS7YMIHP.js → chunk-OE6VHHN4.js} +135 -36
- package/{src-MOKZQTH2.js → chunk-QA6RE2GS.js} +249 -28
- package/chunk-SPRVRSEL.js +75 -0
- package/{chunk-YOE3VZFX.js → chunk-SYGF27W7.js} +2 -2
- package/{chunk-LR42WTKN.js → chunk-UNWQVOLY.js} +14 -12
- package/{chunk-SNOBGFNM.js → chunk-UQUIO7LW.js} +47 -6
- package/{chunk-QQYTPGIL.js → chunk-VHHLO5L6.js} +1 -1
- package/{chunk-3LUM7NX5.js → chunk-YFNQ6HZ3.js} +3 -3
- package/{chunk-GDJ7JT2R.js → chunk-YTT3UHUB.js} +1 -1
- package/{ci-WVYVR4XK.js → ci-XJBYXFFJ.js} +10 -10
- package/cli-package.json +2 -1
- package/{config-VYOTYBGS.js → config-4Y46SH5K.js} +8 -8
- package/{config-2MFZVP2N.js → config-H2Q4ABSS.js} +12 -12
- package/{create-OJPLHBRR.js → create-LUYL2QI4.js} +18 -18
- package/{deprecate-V4PKGFF7.js → deprecate-5ANCI2L6.js} +13 -13
- package/{dist-tag-DNLV4VDE.js → dist-tag-SD2CRWIL.js} +8 -8
- package/{docs-LXHDCGL5.js → docs-B6LVNWTP.js} +17 -17
- package/{exec-P32YSP44.js → exec-CJ5KQA72.js} +18 -18
- package/{exec-cache-JZ5PDTOY.js → exec-cache-EE7DAOW2.js} +16 -16
- package/{exec-local-HHA464H4.js → exec-local-HT3VBN6S.js} +15 -15
- package/{help-GVTTOYUL.js → help-GZ44WYDS.js} +4 -4
- package/{init-RENGG74N.js → init-HVXRXFVY.js} +10 -10
- package/{install-V6VXOBH2.js → install-E2C7EE6P.js} +16 -16
- package/{list-7N7Y5OXB.js → list-V4V6SHJP.js} +18 -18
- package/{login-D2QSAUJC.js → login-VRFV7MCE.js} +12 -12
- package/{logout-QPOYBQNF.js → logout-SU75R7BN.js} +8 -8
- package/{pack-4YYGXP3A.js → pack-IVGKUXTL.js} +11 -11
- package/package.json +1 -1
- package/{ping-QYRIZONU.js → ping-WB222SDT.js} +8 -8
- package/{pkg-WQTNABKT.js → pkg-LAAFNONA.js} +11 -11
- package/{profile-PRI7WXK7.js → profile-P3AVHRDI.js} +8 -8
- package/{publish-PSBYJQS7.js → publish-IUNB3KH5.js} +17 -17
- package/{query-UFYLQW4N.js → query-XCN55INS.js} +18 -18
- package/{registry-YTJZ3AQD.js → registry-QQLWJHJI.js} +5 -5
- package/registry-client-src-revalidate.js +5940 -5804
- package/{repo-4S6ETFXX.js → repo-BQDWUCX5.js} +17 -17
- package/{reporter-GLWYHI2Y.js → reporter-5BVUNWQ6.js} +13 -13
- package/{run-OU7NUB7A.js → run-QT7DX243.js} +15 -15
- package/{run-exec-QPBY7ULE.js → run-exec-XYUI7GLN.js} +15 -15
- package/security-archive-src-update-expired.js +1 -1
- package/{setup-23QXG473.js → setup-CXDJXRAG.js} +18 -18
- package/{src-3GN7TDNH.js → src-2BUT4WYP.js} +7 -5
- package/src-OKMGXMAD.js +212 -0
- package/{src-575IYJOL.js → src-UBAERP25.js} +14 -14
- package/{token-FCIA3RGD.js → token-CBOK6DMT.js} +8 -8
- package/{uninstall-BQVZVKB5.js → uninstall-27VP46KJ.js} +12 -12
- package/{unpublish-YGJ5HEYF.js → unpublish-F4637OQX.js} +8 -8
- package/{update-WCGV66JK.js → update-NGWLJJ22.js} +15 -15
- package/{version-7EA3UQG7.js → version-WPD2KNVC.js} +13 -13
- package/{view-5FWIENVE.js → view-YKFTRRPD.js} +11 -11
- package/vlr.js +1 -1
- package/vlrx.js +1 -1
- package/vlt.js +1 -1
- package/vlx.js +1 -1
- package/vlxl.js +1 -1
- package/{whoami-O4ZTBIC4.js → whoami-I5Q6RTAP.js} +8 -8
- package/chunk-WD74RJXW.js +0 -75
|
@@ -11,7 +11,7 @@ import {createRequire as _vlt_createRequire} from "node:module";
|
|
|
11
11
|
var require = _vlt_createRequire(import.meta.filename);
|
|
12
12
|
import {
|
|
13
13
|
stderr
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UNWQVOLY.js";
|
|
15
15
|
import {
|
|
16
16
|
urlOpen
|
|
17
17
|
} from "./chunk-APMYKJI2.js";
|
|
@@ -11,36 +11,40 @@ import {createRequire as _vlt_createRequire} from "node:module";
|
|
|
11
11
|
var require = _vlt_createRequire(import.meta.filename);
|
|
12
12
|
import {
|
|
13
13
|
PackageInfoClient
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-5YB6UIC3.js";
|
|
15
15
|
import {
|
|
16
16
|
Monorepo,
|
|
17
17
|
PackageJson,
|
|
18
18
|
PathScurry
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-6G7MTZGS.js";
|
|
20
20
|
import {
|
|
21
21
|
resetCaches
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-SYGF27W7.js";
|
|
23
23
|
import {
|
|
24
24
|
commands,
|
|
25
25
|
defaultValues,
|
|
26
26
|
definition,
|
|
27
27
|
getCommand,
|
|
28
28
|
isRecordField,
|
|
29
|
-
recordFields
|
|
30
|
-
|
|
29
|
+
recordFields,
|
|
30
|
+
storeLinkers
|
|
31
|
+
} from "./chunk-6A3XS52F.js";
|
|
31
32
|
import {
|
|
32
33
|
find,
|
|
33
34
|
load,
|
|
34
35
|
reload,
|
|
35
36
|
save
|
|
36
37
|
} from "./chunk-HTOTG4TS.js";
|
|
38
|
+
import {
|
|
39
|
+
storeRoot
|
|
40
|
+
} from "./chunk-UQUIO7LW.js";
|
|
37
41
|
import {
|
|
38
42
|
assertRecordStringString,
|
|
39
43
|
assertRecordStringT,
|
|
40
44
|
getOptions,
|
|
41
45
|
isObject,
|
|
42
46
|
isRecordStringString
|
|
43
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-G5BSQ6DP.js";
|
|
44
48
|
import {
|
|
45
49
|
error
|
|
46
50
|
} from "./chunk-WZWDS3W4.js";
|
|
@@ -175,7 +179,7 @@ var pairsToRecords = (obj) => {
|
|
|
175
179
|
var recordsToPairs = (obj) => {
|
|
176
180
|
return Object.fromEntries(
|
|
177
181
|
Object.entries(obj).filter(
|
|
178
|
-
([k]) => !(k === "scurry" || k === "packageJson" || k === "monorepo" || k === "projectRoot" || k === "packageInfo")
|
|
182
|
+
([k]) => !(k === "scurry" || k === "packageJson" || k === "monorepo" || k === "projectRoot" || k === "storeRoot" || k === "packageInfo")
|
|
179
183
|
).map(([k, v]) => [
|
|
180
184
|
k,
|
|
181
185
|
k === "command" && v && typeof v === "object" ? (
|
|
@@ -236,6 +240,7 @@ var Config = class _Config {
|
|
|
236
240
|
const asRecords = pairsToRecords(this.parse().values);
|
|
237
241
|
const extras = {
|
|
238
242
|
projectRoot: this.projectRoot,
|
|
243
|
+
storeRoot: storeRoot(asRecords.cache),
|
|
239
244
|
scurry,
|
|
240
245
|
packageJson,
|
|
241
246
|
monorepo: Monorepo.maybeLoad(this.projectRoot, {
|
|
@@ -330,6 +335,9 @@ var Config = class _Config {
|
|
|
330
335
|
parse(args = process.argv) {
|
|
331
336
|
if (isParsed(this)) return this;
|
|
332
337
|
this.#originalArgs = [...args];
|
|
338
|
+
const badLinker = process.env.VLT_STORE_LINKER;
|
|
339
|
+
const fixLinker = badLinker !== void 0 && !storeLinkers.includes(badLinker);
|
|
340
|
+
if (fixLinker) process.env.VLT_STORE_LINKER = "unpack";
|
|
333
341
|
const envKeys = Object.keys(defaultValues).filter(
|
|
334
342
|
(k) => process.env[envKey(k)] !== void 0
|
|
335
343
|
);
|
|
@@ -346,6 +354,10 @@ var Config = class _Config {
|
|
|
346
354
|
const cmdPairs = cmdSpecific ? recordsToPairs(cmdSpecific) : {};
|
|
347
355
|
if (cmdSpecific) this.jack.setConfigValues(cmdPairs);
|
|
348
356
|
this.jack.applyDefaults(p);
|
|
357
|
+
if (p.values["store-linker"] === "auto" && process.platform !== "linux") {
|
|
358
|
+
p.values["store-linker"] = "unpack";
|
|
359
|
+
envValues["store-linker"] = "unpack";
|
|
360
|
+
}
|
|
349
361
|
const values = p.values;
|
|
350
362
|
const explicit = {};
|
|
351
363
|
for (const k of /* @__PURE__ */ new Set([...envKeys, ...cliKeys])) {
|
|
@@ -386,6 +398,12 @@ var Config = class _Config {
|
|
|
386
398
|
if (p.values.verbose && p.values.loglevel === "info") {
|
|
387
399
|
p.values.loglevel = "verbose";
|
|
388
400
|
}
|
|
401
|
+
const { loglevel } = p.values;
|
|
402
|
+
if (fixLinker && loglevel !== "silent" && loglevel !== "error") {
|
|
403
|
+
console.error(
|
|
404
|
+
`Warning: invalid VLT_STORE_LINKER ${JSON.stringify(badLinker)}, using ${p.values["store-linker"]}`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
389
407
|
if (!isParsed(this)) throw error("failed to parse config");
|
|
390
408
|
return this;
|
|
391
409
|
}
|
|
@@ -16,10 +16,10 @@ import {
|
|
|
16
16
|
} from "./chunk-ZWKI5OSF.js";
|
|
17
17
|
import {
|
|
18
18
|
minimatch
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-6G7MTZGS.js";
|
|
20
20
|
import {
|
|
21
21
|
Spec
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-G5NJ7CYI.js";
|
|
23
23
|
import {
|
|
24
24
|
parse,
|
|
25
25
|
stringify
|
|
@@ -20,22 +20,25 @@ import {
|
|
|
20
20
|
pickManifest,
|
|
21
21
|
resolve,
|
|
22
22
|
revs
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-6G7MTZGS.js";
|
|
24
24
|
import {
|
|
25
25
|
Spec
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-G5NJ7CYI.js";
|
|
27
27
|
import {
|
|
28
|
-
registryErrorMessage
|
|
29
|
-
|
|
28
|
+
registryErrorMessage,
|
|
29
|
+
storeRoot,
|
|
30
|
+
tokenRefusalAdvice
|
|
31
|
+
} from "./chunk-UQUIO7LW.js";
|
|
30
32
|
import {
|
|
31
33
|
logRequest
|
|
32
34
|
} from "./chunk-U7TEQCBN.js";
|
|
33
|
-
import {
|
|
34
|
-
asPackument
|
|
35
|
-
} from "./chunk-VFBCWAOC.js";
|
|
36
35
|
import {
|
|
37
36
|
XDG
|
|
38
37
|
} from "./chunk-XNLSTHDK.js";
|
|
38
|
+
import {
|
|
39
|
+
asPackument,
|
|
40
|
+
integrityHex
|
|
41
|
+
} from "./chunk-G5BSQ6DP.js";
|
|
39
42
|
import {
|
|
40
43
|
error
|
|
41
44
|
} from "./chunk-WZWDS3W4.js";
|
|
@@ -63,6 +66,59 @@ import {
|
|
|
63
66
|
} from "node:path";
|
|
64
67
|
import { debuglog } from "node:util";
|
|
65
68
|
|
|
69
|
+
// ../../src/package-info/src/capabilities.ts
|
|
70
|
+
var none = Object.freeze({});
|
|
71
|
+
var asked = /* @__PURE__ */ new Map();
|
|
72
|
+
var known = /* @__PURE__ */ new Map();
|
|
73
|
+
var peekCapabilities = (client, registry) => {
|
|
74
|
+
const url = capabilitiesUrl(registry);
|
|
75
|
+
const seen = known.get(url);
|
|
76
|
+
if (seen) return seen;
|
|
77
|
+
void getCapabilities(client, registry);
|
|
78
|
+
return void 0;
|
|
79
|
+
};
|
|
80
|
+
var getCapabilities = async (client, registry) => {
|
|
81
|
+
const url = capabilitiesUrl(registry);
|
|
82
|
+
const seen = asked.get(url);
|
|
83
|
+
if (seen) return seen;
|
|
84
|
+
const doc = fetchCapabilities(client, url).then((caps) => {
|
|
85
|
+
known.set(url, caps);
|
|
86
|
+
return caps;
|
|
87
|
+
});
|
|
88
|
+
asked.set(url, doc);
|
|
89
|
+
return doc;
|
|
90
|
+
};
|
|
91
|
+
var capabilitiesUrl = (registry) => String(new URL("-/vlt/capabilities", registry));
|
|
92
|
+
var fetchCapabilities = async (client, url) => {
|
|
93
|
+
try {
|
|
94
|
+
const response = await client.request(url, {
|
|
95
|
+
headers: { accept: "application/json" }
|
|
96
|
+
});
|
|
97
|
+
if (response.statusCode !== 200) return none;
|
|
98
|
+
return asCapabilities(response.json());
|
|
99
|
+
} catch {
|
|
100
|
+
return none;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var asCapabilities = (body) => {
|
|
104
|
+
if (typeof body !== "object" || body === null) return none;
|
|
105
|
+
const doc = body;
|
|
106
|
+
const caps = {};
|
|
107
|
+
for (const key of [
|
|
108
|
+
"manifests",
|
|
109
|
+
"resolve",
|
|
110
|
+
"stable-filter"
|
|
111
|
+
]) {
|
|
112
|
+
const version = doc[key];
|
|
113
|
+
if (typeof version === "string") caps[key] = version;
|
|
114
|
+
}
|
|
115
|
+
const { mimeTypes } = doc;
|
|
116
|
+
if (Array.isArray(mimeTypes) && mimeTypes.every((type) => typeof type === "string")) {
|
|
117
|
+
caps.mimeTypes = mimeTypes;
|
|
118
|
+
}
|
|
119
|
+
return caps;
|
|
120
|
+
};
|
|
121
|
+
|
|
66
122
|
// ../../src/package-info/src/rename.ts
|
|
67
123
|
import { rename as fsRename, rm } from "node:fs/promises";
|
|
68
124
|
var { platform } = process;
|
|
@@ -86,13 +142,20 @@ var rename = platform !== "win32" ? fsRename : (async function(oldPath, newPath)
|
|
|
86
142
|
var debug = debuglog("vlt");
|
|
87
143
|
var xdg = new XDG("vlt");
|
|
88
144
|
var delimiter = "~";
|
|
89
|
-
var
|
|
145
|
+
var VLT_PACKUMENT_MIME = "application/vnd.vlt.packument-v1+json";
|
|
146
|
+
var PACKUMENT_ACCEPT = `${VLT_PACKUMENT_MIME}; q=1.0, application/json; q=0.8, */*; q=0.1`;
|
|
90
147
|
var manifestCacheMaxAge = 5 * 60 * 1e3;
|
|
91
148
|
var noRegistryError = (spec) => error(
|
|
92
149
|
'No registry configured to resolve this spec. Set "registry" in vlt.json, pass --registry, or run `vlt login --registry=<url>`. See https://docs.vlt.sh/cli',
|
|
93
150
|
{ code: "ECONFIG", spec }
|
|
94
151
|
);
|
|
95
152
|
var isMovingSelector = (f) => !!(f.distTag || f.range?.isAny);
|
|
153
|
+
var isStableSelector = (f) => {
|
|
154
|
+
const { range } = f;
|
|
155
|
+
if (!range) return false;
|
|
156
|
+
return !range.isAny && !range.raw.includes("-");
|
|
157
|
+
};
|
|
158
|
+
var storeLinkers = /* @__PURE__ */ new Set(["auto", "hardlink", "copy"]);
|
|
96
159
|
var PackageInfoClient = class {
|
|
97
160
|
#registryClient;
|
|
98
161
|
#projectRoot;
|
|
@@ -102,8 +165,26 @@ var PackageInfoClient = class {
|
|
|
102
165
|
packageJson;
|
|
103
166
|
monorepo;
|
|
104
167
|
#trustedIntegrities = /* @__PURE__ */ new Map();
|
|
168
|
+
// `${registry}${name}` of every packument served as VLT_PACKUMENT_MIME
|
|
169
|
+
#vltPackuments = /* @__PURE__ */ new Set();
|
|
105
170
|
#manifestCacheMinAge = Date.now() - manifestCacheMaxAge;
|
|
106
171
|
#cachePath;
|
|
172
|
+
#storeRoot;
|
|
173
|
+
#storeLinker;
|
|
174
|
+
#storeHits = { link: 0, copy: 0 };
|
|
175
|
+
#storeMisses = 0;
|
|
176
|
+
#storeHitRateLogged = false;
|
|
177
|
+
#logStoreHitRate = () => {
|
|
178
|
+
const { link, copy } = this.#storeHits;
|
|
179
|
+
const n = Math.max(1, link + copy + this.#storeMisses);
|
|
180
|
+
debug(
|
|
181
|
+
"global store: linked=%d copied=%d missed=%d hit rate=%s%%",
|
|
182
|
+
link,
|
|
183
|
+
copy,
|
|
184
|
+
this.#storeMisses,
|
|
185
|
+
((link + copy) / n * 100).toFixed(1)
|
|
186
|
+
);
|
|
187
|
+
};
|
|
107
188
|
// In-flight coalescing key is `${registry}${name}` — no representation
|
|
108
189
|
// component. Safe only because every caller requests the same full
|
|
109
190
|
// packument (see #fetchPackument). The one thing that does vary per
|
|
@@ -123,15 +204,47 @@ var PackageInfoClient = class {
|
|
|
123
204
|
#tarPoolPromise;
|
|
124
205
|
async getRegistryClient() {
|
|
125
206
|
if (this.#registryClient) return this.#registryClient;
|
|
126
|
-
this.#registryClientPromise ??= import("./src-
|
|
207
|
+
this.#registryClientPromise ??= import("./src-2BUT4WYP.js").then(({ RegistryClient }) => {
|
|
127
208
|
this.#registryClient = new RegistryClient(this.options);
|
|
128
209
|
return this.#registryClient;
|
|
129
210
|
});
|
|
130
211
|
return this.#registryClientPromise;
|
|
131
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* The vlt extensions `registry` serves, from its
|
|
215
|
+
* `GET /-/vlt/capabilities` document. A registry that does not answer
|
|
216
|
+
* one reads as an empty document, so a missing key means unsupported.
|
|
217
|
+
*/
|
|
218
|
+
async capabilities(registry) {
|
|
219
|
+
return getCapabilities(await this.getRegistryClient(), registry);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Whether the packument for `f` can be fetched with `?stable`: the
|
|
223
|
+
* selector has to be one a prerelease cannot answer, and the registry
|
|
224
|
+
* must not have told us it does not serve the filter.
|
|
225
|
+
*
|
|
226
|
+
* Never waits on the capability document, which would put a round trip in
|
|
227
|
+
* front of the first packument of every cold install. Until that document
|
|
228
|
+
* arrives the answer is yes: a registry that does not know `?stable`
|
|
229
|
+
* ignores the parameter and serves the full packument, which resolution
|
|
230
|
+
* reads just as well. Once the document does arrive it is authoritative,
|
|
231
|
+
* so a registry that does not serve the filter stops being asked with it.
|
|
232
|
+
*/
|
|
233
|
+
#stable(f) {
|
|
234
|
+
const { registry } = f;
|
|
235
|
+
if (!registry || !isStableSelector(f)) return false;
|
|
236
|
+
const client = this.#registryClient;
|
|
237
|
+
if (!client) {
|
|
238
|
+
void this.capabilities(registry).catch(() => {
|
|
239
|
+
});
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
const caps = peekCapabilities(client, registry);
|
|
243
|
+
return !caps || !!caps["stable-filter"];
|
|
244
|
+
}
|
|
132
245
|
async getTarPool() {
|
|
133
246
|
if (this.#tarPool) return this.#tarPool;
|
|
134
|
-
this.#tarPoolPromise ??= import("./src-
|
|
247
|
+
this.#tarPoolPromise ??= import("./src-OKMGXMAD.js").then(
|
|
135
248
|
({ Pool }) => {
|
|
136
249
|
this.#tarPool = new Pool();
|
|
137
250
|
return this.#tarPool;
|
|
@@ -154,6 +267,9 @@ var PackageInfoClient = class {
|
|
|
154
267
|
packageJson: this.packageJson
|
|
155
268
|
});
|
|
156
269
|
this.#cachePath = options.cache ?? xdg.cache();
|
|
270
|
+
this.#storeRoot = options.storeRoot ?? storeRoot(this.#cachePath);
|
|
271
|
+
const linker = options["store-linker"];
|
|
272
|
+
this.#storeLinker = linker && storeLinkers.has(linker) ? linker : "unpack";
|
|
157
273
|
void mkdir(pathResolve(this.#cachePath, "package-info"), {
|
|
158
274
|
recursive: true
|
|
159
275
|
}).catch(() => {
|
|
@@ -166,7 +282,8 @@ var PackageInfoClient = class {
|
|
|
166
282
|
from = this.#projectRoot,
|
|
167
283
|
integrity,
|
|
168
284
|
resolved,
|
|
169
|
-
fromLockfile = false
|
|
285
|
+
fromLockfile = false,
|
|
286
|
+
installScripts = false
|
|
170
287
|
} = options;
|
|
171
288
|
const f = spec.final;
|
|
172
289
|
const alreadyResolved = !!(integrity && resolved);
|
|
@@ -204,14 +321,44 @@ var PackageInfoClient = class {
|
|
|
204
321
|
}
|
|
205
322
|
}
|
|
206
323
|
case "registry": {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
)
|
|
324
|
+
const pool = await this.getTarPool();
|
|
325
|
+
const hex = f.type === "registry" && this.#storeLinker !== "unpack" ? integrityHex(r.integrity) : void 0;
|
|
326
|
+
const copy = this.#storeLinker === "copy" || installScripts;
|
|
327
|
+
if (hex) {
|
|
328
|
+
if (debug.enabled && !this.#storeHitRateLogged) {
|
|
329
|
+
this.#storeHitRateLogged = true;
|
|
330
|
+
process.once("beforeExit", this.#logStoreHitRate);
|
|
331
|
+
}
|
|
332
|
+
const linked = await pool.linkFromStore(
|
|
333
|
+
pathResolve(this.#storeRoot, hex),
|
|
334
|
+
target,
|
|
335
|
+
{ copy }
|
|
336
|
+
);
|
|
337
|
+
if (linked) {
|
|
338
|
+
const { how, index } = linked;
|
|
339
|
+
this.#storeHits[how]++;
|
|
340
|
+
logRequest(r.resolved, how === "link" ? "store" : "cache");
|
|
341
|
+
return {
|
|
342
|
+
...r,
|
|
343
|
+
manifest: index.manifest,
|
|
344
|
+
// implies scripts, so most packages skip the scan
|
|
345
|
+
bindingGyp: index.scripts && index.files.some((f2) => f2[0] === "binding.gyp")
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
this.#storeMisses++;
|
|
349
|
+
}
|
|
350
|
+
const rc = await this.getRegistryClient();
|
|
351
|
+
const cached = rc.cachedBody(r.resolved, {
|
|
352
|
+
integrity: r.integrity
|
|
353
|
+
});
|
|
211
354
|
if (cached) {
|
|
212
355
|
try {
|
|
213
|
-
await
|
|
356
|
+
await pool.unpack(cached.body, target);
|
|
214
357
|
logRequest(r.resolved, "cache");
|
|
358
|
+
r.integrity ??= cached.integrity;
|
|
359
|
+
if (hex || cached.gzip) {
|
|
360
|
+
rc.queueForStore(cached.key, r.integrity);
|
|
361
|
+
}
|
|
215
362
|
return r;
|
|
216
363
|
} catch (er) {
|
|
217
364
|
debug(
|
|
@@ -226,6 +373,7 @@ var PackageInfoClient = class {
|
|
|
226
373
|
const response = await (await this.getRegistryClient()).request(r.resolved, {
|
|
227
374
|
integrity: r.integrity,
|
|
228
375
|
trustIntegrity,
|
|
376
|
+
verifyDigest: r.digestRequired ? "required" : true,
|
|
229
377
|
...useCache === false ? { useCache } : {}
|
|
230
378
|
});
|
|
231
379
|
if (response.statusCode !== 200) {
|
|
@@ -246,19 +394,25 @@ var PackageInfoClient = class {
|
|
|
246
394
|
);
|
|
247
395
|
}
|
|
248
396
|
const buf2 = response.buffer();
|
|
249
|
-
if (r.integrity
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
397
|
+
if (r.integrity) {
|
|
398
|
+
if (!fromLockfile && !response.fromCache) {
|
|
399
|
+
const hash = createHash("sha512");
|
|
400
|
+
hash.update(buf2);
|
|
401
|
+
const computed = `sha512-${hash.digest("base64")}`;
|
|
402
|
+
if (computed !== r.integrity) {
|
|
403
|
+
throw error("Tarball integrity check failed", {
|
|
404
|
+
code: "EINTEGRITY",
|
|
405
|
+
spec,
|
|
406
|
+
url: r.resolved,
|
|
407
|
+
wanted: r.integrity,
|
|
408
|
+
found: computed
|
|
409
|
+
});
|
|
410
|
+
}
|
|
261
411
|
}
|
|
412
|
+
} else if (response.fromCache) {
|
|
413
|
+
r.integrity = response.integrity;
|
|
414
|
+
} else {
|
|
415
|
+
r.integrity = response.integrityActual;
|
|
262
416
|
}
|
|
263
417
|
return buf2;
|
|
264
418
|
};
|
|
@@ -460,6 +614,9 @@ var PackageInfoClient = class {
|
|
|
460
614
|
...options,
|
|
461
615
|
integrity,
|
|
462
616
|
trustIntegrity,
|
|
617
|
+
// no dist.integrity: checked against the digest the registry
|
|
618
|
+
// sent with it instead, before the client caches it
|
|
619
|
+
verifyDigest: this.#vltPackuments.has(`${f.registry}${f.name}`) ? "required" : true,
|
|
463
620
|
...useCache === false ? { useCache } : {}
|
|
464
621
|
});
|
|
465
622
|
if (response.statusCode !== 200) {
|
|
@@ -595,21 +752,30 @@ var PackageInfoClient = class {
|
|
|
595
752
|
});
|
|
596
753
|
throw new Error("manifest cache expired");
|
|
597
754
|
}
|
|
755
|
+
if (json.__VLT_PACKUMENT) {
|
|
756
|
+
this.#vltPackuments.add(`${f.registry}${f.name}`);
|
|
757
|
+
delete json.__VLT_PACKUMENT;
|
|
758
|
+
}
|
|
598
759
|
return json;
|
|
599
760
|
} catch {
|
|
600
761
|
}
|
|
601
762
|
}
|
|
602
763
|
const mani = pickManifest(
|
|
603
|
-
await this
|
|
764
|
+
await this.#packument(f, options, this.#stable(f)),
|
|
604
765
|
spec,
|
|
605
766
|
options
|
|
606
767
|
);
|
|
607
768
|
if (!mani) throw this.#resolveError(spec, options);
|
|
608
769
|
if (cachePath && !this.#manifestWritePaths.has(cachePath)) {
|
|
609
770
|
this.#manifestWritePaths.add(cachePath);
|
|
771
|
+
const vlt = this.#vltPackuments.has(
|
|
772
|
+
`${f.registry}${f.name}`
|
|
773
|
+
);
|
|
610
774
|
void this.#writeManifestCache(
|
|
611
775
|
cachePath,
|
|
612
|
-
JSON.stringify(
|
|
776
|
+
JSON.stringify(
|
|
777
|
+
vlt ? { ...mani, __VLT_PACKUMENT: true } : mani
|
|
778
|
+
)
|
|
613
779
|
);
|
|
614
780
|
}
|
|
615
781
|
return mani;
|
|
@@ -699,7 +865,15 @@ var PackageInfoClient = class {
|
|
|
699
865
|
}
|
|
700
866
|
}
|
|
701
867
|
}
|
|
868
|
+
/**
|
|
869
|
+
* The packument for `spec`, with every version the registry has. Callers
|
|
870
|
+
* that only pick a manifest out of it go through `#packument` instead,
|
|
871
|
+
* which can ask for the prerelease-free one.
|
|
872
|
+
*/
|
|
702
873
|
async packument(spec, options = {}) {
|
|
874
|
+
return this.#packument(spec, options, false);
|
|
875
|
+
}
|
|
876
|
+
async #packument(spec, options, stable) {
|
|
703
877
|
if (typeof spec === "string")
|
|
704
878
|
spec = Spec.parse(spec, this.options);
|
|
705
879
|
const f = spec.final;
|
|
@@ -738,12 +912,25 @@ var PackageInfoClient = class {
|
|
|
738
912
|
case "registry": {
|
|
739
913
|
const { registry, name } = f;
|
|
740
914
|
if (!registry) throw noRegistryError(spec);
|
|
741
|
-
|
|
915
|
+
if (options.full)
|
|
916
|
+
return this.#fetchPackument(
|
|
917
|
+
spec,
|
|
918
|
+
options,
|
|
919
|
+
new URL(name, registry)
|
|
920
|
+
);
|
|
921
|
+
const fullKey = `${registry}${name}`;
|
|
922
|
+
const packumentKey = stable ? `${fullKey}?stable` : fullKey;
|
|
742
923
|
const forced = isMovingSelector(f);
|
|
743
|
-
const inflight = this.#packumentPromises.get(packumentKey)
|
|
924
|
+
const inflight = this.#packumentPromises.get(packumentKey) ?? // the full packument is a superset of the stable one, so an
|
|
925
|
+
// in-flight full request answers a stable ask too, and a package
|
|
926
|
+
// wanted both ways is still fetched once
|
|
927
|
+
(stable ? this.#packumentPromises.get(fullKey) : void 0);
|
|
744
928
|
if (inflight && (!forced || inflight.forced))
|
|
745
929
|
return inflight.promise;
|
|
746
|
-
const pakuURL = new URL(
|
|
930
|
+
const pakuURL = new URL(
|
|
931
|
+
stable ? `${name}?stable` : name,
|
|
932
|
+
registry
|
|
933
|
+
);
|
|
747
934
|
const promise = this.#fetchPackument(spec, options, pakuURL);
|
|
748
935
|
const record = { promise, forced };
|
|
749
936
|
this.#packumentPromises.set(packumentKey, record);
|
|
@@ -759,8 +946,10 @@ var PackageInfoClient = class {
|
|
|
759
946
|
}
|
|
760
947
|
async #fetchPackument(spec, options, pakuURL, useCache) {
|
|
761
948
|
const response = await (await this.getRegistryClient()).request(pakuURL, {
|
|
762
|
-
headers: {
|
|
763
|
-
|
|
949
|
+
headers: {
|
|
950
|
+
accept: options.full ? "application/json" : PACKUMENT_ACCEPT
|
|
951
|
+
},
|
|
952
|
+
...useCache === false || options.full ? { useCache: false } : {},
|
|
764
953
|
// costs a conditional GET per moving selector on an otherwise warm
|
|
765
954
|
// cache, install included. 304s are cheap but not free; the
|
|
766
955
|
// alternative is serving a dist tag that moved (#1656).
|
|
@@ -777,14 +966,21 @@ var PackageInfoClient = class {
|
|
|
777
966
|
}
|
|
778
967
|
);
|
|
779
968
|
}
|
|
969
|
+
let paku;
|
|
780
970
|
try {
|
|
781
|
-
|
|
971
|
+
paku = response.json();
|
|
782
972
|
} catch (er) {
|
|
783
973
|
if (useCache !== false) {
|
|
784
974
|
return this.#fetchPackument(spec, options, pakuURL, false);
|
|
785
975
|
}
|
|
786
976
|
throw er;
|
|
787
977
|
}
|
|
978
|
+
const { registry, name } = spec.final;
|
|
979
|
+
if (response.contentType.startsWith(VLT_PACKUMENT_MIME)) {
|
|
980
|
+
this.#vltPackuments.add(`${registry}${name}`);
|
|
981
|
+
}
|
|
982
|
+
if (registry) absolutizeTarballs(paku, registry);
|
|
983
|
+
return paku;
|
|
788
984
|
}
|
|
789
985
|
async resolve(spec, options = {}) {
|
|
790
986
|
const memoKey = String(spec);
|
|
@@ -839,6 +1035,9 @@ var PackageInfoClient = class {
|
|
|
839
1035
|
signatures,
|
|
840
1036
|
spec
|
|
841
1037
|
};
|
|
1038
|
+
if (!integrity && this.#vltPackuments.has(`${f.registry}${f.name}`)) {
|
|
1039
|
+
r.digestRequired = true;
|
|
1040
|
+
}
|
|
842
1041
|
this.#resolutions.set(memoKey, r);
|
|
843
1042
|
return r;
|
|
844
1043
|
}
|
|
@@ -922,8 +1121,10 @@ var PackageInfoClient = class {
|
|
|
922
1121
|
// error resolving
|
|
923
1122
|
#resolveError(spec, options = {}, message = "Could not resolve", extra = {}) {
|
|
924
1123
|
const { from = this.#projectRoot } = options;
|
|
1124
|
+
const advice = spec?.final.type === "registry" ? tokenRefusalAdvice(extra.response, extra.url) : void 0;
|
|
925
1125
|
const er = error(
|
|
926
|
-
message
|
|
1126
|
+
advice ? `${message}
|
|
1127
|
+
\u26A0\uFE0F ${advice}` : message,
|
|
927
1128
|
{
|
|
928
1129
|
code: "ERESOLVE",
|
|
929
1130
|
spec,
|
|
@@ -935,6 +1136,15 @@ var PackageInfoClient = class {
|
|
|
935
1136
|
return er;
|
|
936
1137
|
}
|
|
937
1138
|
};
|
|
1139
|
+
var absolutizeTarballs = (paku, registry) => {
|
|
1140
|
+
const base = registry.endsWith("/") ? registry : registry + "/";
|
|
1141
|
+
for (const { dist } of Object.values(paku.versions)) {
|
|
1142
|
+
const tarball = dist?.tarball;
|
|
1143
|
+
if (tarball && !/^[a-z][a-z0-9+.-]*:/i.test(tarball)) {
|
|
1144
|
+
dist.tarball = String(new URL(tarball, base));
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
938
1148
|
|
|
939
1149
|
export {
|
|
940
1150
|
PackageInfoClient
|
|
@@ -1164,6 +1164,12 @@ var recordFields = [
|
|
|
1164
1164
|
"jsr-registries"
|
|
1165
1165
|
];
|
|
1166
1166
|
var isRecordField = (s) => recordFields.includes(s);
|
|
1167
|
+
var storeLinkers = [
|
|
1168
|
+
"auto",
|
|
1169
|
+
"hardlink",
|
|
1170
|
+
"copy",
|
|
1171
|
+
"unpack"
|
|
1172
|
+
];
|
|
1167
1173
|
var j2 = jack({
|
|
1168
1174
|
envPrefix: "VLT",
|
|
1169
1175
|
allowPositionals: true,
|
|
@@ -1357,6 +1363,32 @@ var definition = j2.heading("Configuration").description(
|
|
|
1357
1363
|
`,
|
|
1358
1364
|
default: cacheDir
|
|
1359
1365
|
},
|
|
1366
|
+
"store-linker": {
|
|
1367
|
+
hint: "auto | hardlink | copy | unpack",
|
|
1368
|
+
description: `How packages are placed in \`node_modules\`. Every
|
|
1369
|
+
linker but \`unpack\` fills a global store under
|
|
1370
|
+
\`cache\` in the background, then places packages
|
|
1371
|
+
from it.
|
|
1372
|
+
|
|
1373
|
+
- auto: Default. On Linux, hardlink from the global
|
|
1374
|
+
store, copying any file that cannot be linked.
|
|
1375
|
+
Elsewhere, same as \`unpack\`: a hardlink is the
|
|
1376
|
+
slowest way to place a file on APFS, so macOS and
|
|
1377
|
+
Windows unpack by default.
|
|
1378
|
+
- hardlink: Hardlink from the global store on every
|
|
1379
|
+
platform.
|
|
1380
|
+
- copy: Copy from the global store. Use this when
|
|
1381
|
+
editing files in \`node_modules\` in place, since
|
|
1382
|
+
a hardlink shares its content with every project.
|
|
1383
|
+
- unpack: Unpack each package tarball, skipping the
|
|
1384
|
+
global store.
|
|
1385
|
+
|
|
1386
|
+
Packages with install scripts are always copied.
|
|
1387
|
+
An invalid \`VLT_STORE_LINKER\` warns and uses
|
|
1388
|
+
\`unpack\`.`,
|
|
1389
|
+
validOptions: storeLinkers,
|
|
1390
|
+
default: "auto"
|
|
1391
|
+
},
|
|
1360
1392
|
tag: {
|
|
1361
1393
|
description: `Default \`dist-tag\` to install or publish`,
|
|
1362
1394
|
default: "latest"
|
|
@@ -1847,6 +1879,7 @@ export {
|
|
|
1847
1879
|
getCommand,
|
|
1848
1880
|
recordFields,
|
|
1849
1881
|
isRecordField,
|
|
1882
|
+
storeLinkers,
|
|
1850
1883
|
definition,
|
|
1851
1884
|
defaultValues,
|
|
1852
1885
|
getSortedCliOptions,
|
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
graphRun,
|
|
14
14
|
graphRunSync,
|
|
15
15
|
joinDepIDTuple
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-SYGF27W7.js";
|
|
17
17
|
import {
|
|
18
18
|
Spec
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-G5NJ7CYI.js";
|
|
20
20
|
import {
|
|
21
21
|
load,
|
|
22
22
|
parse as parse2,
|
|
@@ -28,6 +28,9 @@ import {
|
|
|
28
28
|
promiseSpawn,
|
|
29
29
|
whichSync
|
|
30
30
|
} from "./chunk-U7TEQCBN.js";
|
|
31
|
+
import {
|
|
32
|
+
ts
|
|
33
|
+
} from "./chunk-VE6CCH33.js";
|
|
31
34
|
import {
|
|
32
35
|
Range,
|
|
33
36
|
Version,
|
|
@@ -38,10 +41,7 @@ import {
|
|
|
38
41
|
normalizeManifest,
|
|
39
42
|
parse,
|
|
40
43
|
satisfies
|
|
41
|
-
} from "./chunk-
|
|
42
|
-
import {
|
|
43
|
-
ts
|
|
44
|
-
} from "./chunk-VE6CCH33.js";
|
|
44
|
+
} from "./chunk-G5BSQ6DP.js";
|
|
45
45
|
import {
|
|
46
46
|
error
|
|
47
47
|
} from "./chunk-WZWDS3W4.js";
|