@vltpkg/cli-js 1.0.2 → 1.0.3
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-DB347PPG.js → access-5WETTBDZ.js} +9 -7
- package/{bugs-QBKI62J6.js → bugs-KONFLIQQ.js} +19 -18
- package/{build-EFJ3FFGU.js → build-S7G2DU7I.js} +12 -10
- package/{cache-BQJCMDJN.js → cache-Z4OIMLXQ.js} +23 -21
- package/{chunk-RXNA2XCX.js → chunk-4KCU2KZL.js} +8 -1
- package/{chunk-3MBSXZ62.js → chunk-5B23EKN4.js} +4 -4
- package/{chunk-5OGQND6H.js → chunk-5QJEOGEM.js} +3 -1
- package/{chunk-DEMBZY23.js → chunk-5UPPEUG2.js} +11 -11
- package/chunk-BJBFEQRR.js +667 -0
- package/{chunk-L34LR5DV.js → chunk-DYCF76WI.js} +4 -4
- package/{chunk-ULCDRVY2.js → chunk-E737X73P.js} +38 -24
- package/{chunk-F2GLBPGQ.js → chunk-FFOXTPQA.js} +8 -6
- package/chunk-G7UPIJAP.js +903 -0
- package/{chunk-CNSTFT7U.js → chunk-HAYXR3MW.js} +1 -1
- package/{chunk-3HUTU5SO.js → chunk-HNCE3YE5.js} +1649 -1569
- package/{chunk-Q46JRSZU.js → chunk-IITIX4ID.js} +22 -3
- package/chunk-LPIBYUMT.js +854 -0
- package/{chunk-47IR6Z6C.js → chunk-LZGKX7JI.js} +87 -40
- package/{chunk-5PFGKHIS.js → chunk-NXEH3NQZ.js} +10 -10
- package/{chunk-FM5DQZVN.js → chunk-OCJDISSI.js} +2 -2
- package/chunk-RNJSI3NZ.js +75 -0
- package/{chunk-ONVLPT73.js → chunk-T4GYDWUJ.js} +1 -1
- package/{chunk-YDUHQU7N.js → chunk-TMBNGWXK.js} +3 -3
- package/{chunk-CTDFRLS4.js → chunk-UAAZW4N6.js} +4 -4
- package/{chunk-TM4LHSZV.js → chunk-UXIRAU5T.js} +3 -3
- package/{chunk-BSB4XGBB.js → chunk-VB3IWNHX.js} +1 -1
- package/chunk-VE6CCH33.js +3000 -0
- package/{chunk-42UTZKAU.js → chunk-W2Q5EIMH.js} +8 -8
- package/{chunk-YRMICBI4.js → chunk-XQSBCMSC.js} +5 -5
- package/{chunk-NS4VFXHX.js → chunk-XU5SMHXP.js} +1 -1
- package/{ci-A22A6TCQ.js → ci-RZZE375O.js} +17 -16
- package/cli-package.json +1 -1
- package/{config-JL4TW2AV.js → config-LL3RLMZG.js} +9 -12
- package/{config-VOLRKFYD.js → config-MDFY3ORD.js} +15 -18
- package/{create-SL7HEXCS.js → create-GVSDTOGQ.js} +23 -23
- package/{deprecate-ZK525LQW.js → deprecate-T4TQLGXQ.js} +16 -14
- package/{dist-tag-FY3FB5VH.js → dist-tag-GO46UQUN.js} +11 -9
- package/{docs-6BPWZJFW.js → docs-FJME563T.js} +19 -18
- package/{exec-JZ5J7DI7.js → exec-M22KBPCK.js} +23 -23
- package/{exec-cache-VGSXKZVF.js → exec-cache-3UNLDUAP.js} +22 -22
- package/{exec-local-GPZUSOSM.js → exec-local-YHVO5RLU.js} +20 -18
- package/{help-XI7TNIRU.js → help-ZEWMLOJX.js} +3 -3
- package/{init-6KWM7CDI.js → init-4HPZY2KN.js} +12 -10
- package/{install-4VLOKCWH.js → install-2TZIP4PJ.js} +18 -17
- package/{list-3VLGWGKU.js → list-NFFXER43.js} +20 -18
- package/{login-3DGPSWCG.js → login-KV5YC5Z2.js} +9 -7
- package/{logout-DBFMZC6J.js → logout-I2VT3NAR.js} +9 -7
- package/{pack-LHNYEZ5W.js → pack-47ZKFSHI.js} +16 -14
- package/package.json +1 -1
- package/{ping-VLLX5LIH.js → ping-Q7Y7QV63.js} +9 -7
- package/{pkg-FYPUMX7U.js → pkg-VTJS2ISJ.js} +13 -11
- package/{profile-FOQ74TB7.js → profile-YXZYVEUX.js} +9 -7
- package/{publish-DFURU7DW.js → publish-CBN67KN2.js} +21 -19
- package/{query-NC3EABMW.js → query-U3QHF3ZE.js} +20 -18
- package/{registry-5DUFCPD6.js → registry-CZPFR3OF.js} +3 -3
- package/registry-client-package.json +1 -1
- package/registry-client-src-revalidate.js +403 -328
- package/{repo-IZXACKQ2.js → repo-4UIQRBI7.js} +19 -18
- package/{chunk-UVZJFBYE.js → reporter-DKZTTACW.js} +5 -5
- package/{run-RDFVO7FY.js → run-5DUYI6GL.js} +20 -18
- package/{run-exec-OGMXEVN5.js → run-exec-HPNBVAXH.js} +20 -18
- package/security-archive-src-update-expired.js +11 -2
- package/{setup-KTJQPDJB.js → setup-23W5FQVW.js} +15 -13
- package/{src-BJU7XZNK.js → src-2NB67FPG.js} +22 -23
- package/{reporter-UU654STB.js → src-6OKPBJJT.js} +42 -7
- package/src-M5RRGKUM.js +913 -0
- package/{token-SKICECA4.js → token-SRCS5CRU.js} +9 -7
- package/{uninstall-MTZJ33TO.js → uninstall-JXHAFXZ2.js} +18 -17
- package/{unpublish-3QBJZFHQ.js → unpublish-GRYB5KQH.js} +12 -10
- package/{update-TH477PKA.js → update-GDLL4ER6.js} +17 -16
- package/{version-YIBQZLQS.js → version-JVG4CI4L.js} +13 -11
- package/{view-FG74OAOV.js → view-ABQLVL4L.js} +12 -14
- 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-LHJ4PRJQ.js → whoami-RCCZ7BXI.js} +9 -7
- package/chunk-7NHXV6AH.js +0 -4488
- package/chunk-WAFERMRI.js +0 -1663
- package/chunk-ZLZ4XF46.js +0 -75
- package/{chunk-Y7CQIZ7Y.js → chunk-FEIPJIEN.js} +3 -3
|
@@ -0,0 +1,903 @@
|
|
|
1
|
+
var global = globalThis;
|
|
2
|
+
import {Buffer} from "node:buffer";
|
|
3
|
+
import {setTimeout as _vlt_setTimeout,clearTimeout as _vlt_clearTimeout,setImmediate as _vlt_setImmediate,clearImmediate as _vlt_clearImmediate,setInterval as _vlt_setInterval,clearInterval as _vlt_clearInterval} from "node:timers";
|
|
4
|
+
globalThis.setTimeout = _vlt_setTimeout;
|
|
5
|
+
globalThis.clearTimeout = _vlt_clearTimeout;
|
|
6
|
+
globalThis.setImmediate = _vlt_setImmediate;
|
|
7
|
+
globalThis.clearImmediate = _vlt_clearImmediate;
|
|
8
|
+
globalThis.setInterval = _vlt_setInterval;
|
|
9
|
+
globalThis.clearInterval = _vlt_clearInterval;
|
|
10
|
+
import {createRequire as _vlt_createRequire} from "node:module";
|
|
11
|
+
var require = _vlt_createRequire(import.meta.filename);
|
|
12
|
+
import {
|
|
13
|
+
Qn,
|
|
14
|
+
require_lib
|
|
15
|
+
} from "./chunk-FWKQ7YDF.js";
|
|
16
|
+
import {
|
|
17
|
+
Monorepo,
|
|
18
|
+
PackageJson,
|
|
19
|
+
clone,
|
|
20
|
+
pickManifest,
|
|
21
|
+
resolve,
|
|
22
|
+
revs
|
|
23
|
+
} from "./chunk-FFOXTPQA.js";
|
|
24
|
+
import {
|
|
25
|
+
Spec
|
|
26
|
+
} from "./chunk-XU5SMHXP.js";
|
|
27
|
+
import {
|
|
28
|
+
XDG
|
|
29
|
+
} from "./chunk-XNLSTHDK.js";
|
|
30
|
+
import {
|
|
31
|
+
asPackument
|
|
32
|
+
} from "./chunk-IITIX4ID.js";
|
|
33
|
+
import {
|
|
34
|
+
error
|
|
35
|
+
} from "./chunk-WZWDS3W4.js";
|
|
36
|
+
import {
|
|
37
|
+
__toESM
|
|
38
|
+
} from "./chunk-PZLD7RTK.js";
|
|
39
|
+
|
|
40
|
+
// ../../src/package-info/src/index.ts
|
|
41
|
+
var import_ssri = __toESM(require_lib(), 1);
|
|
42
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
43
|
+
import {
|
|
44
|
+
mkdir,
|
|
45
|
+
readFile,
|
|
46
|
+
rm as rm2,
|
|
47
|
+
stat,
|
|
48
|
+
symlink,
|
|
49
|
+
unlink,
|
|
50
|
+
writeFile
|
|
51
|
+
} from "node:fs/promises";
|
|
52
|
+
import {
|
|
53
|
+
basename,
|
|
54
|
+
dirname,
|
|
55
|
+
resolve as pathResolve,
|
|
56
|
+
relative
|
|
57
|
+
} from "node:path";
|
|
58
|
+
|
|
59
|
+
// ../../src/package-info/src/rename.ts
|
|
60
|
+
import { rename as fsRename, rm } from "node:fs/promises";
|
|
61
|
+
var { platform } = process;
|
|
62
|
+
var rename = platform !== "win32" ? fsRename : (async function(oldPath, newPath) {
|
|
63
|
+
let retries = 3;
|
|
64
|
+
const retry = async (er) => {
|
|
65
|
+
if (retries > 0 && er.code === "EPERM") {
|
|
66
|
+
retries--;
|
|
67
|
+
await rm(newPath, { recursive: true, force: true });
|
|
68
|
+
return fsRename(oldPath, newPath).then(() => {
|
|
69
|
+
}, retry);
|
|
70
|
+
} else {
|
|
71
|
+
throw er;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return fsRename(oldPath, newPath).then(() => {
|
|
75
|
+
}, retry);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// ../../src/package-info/src/index.ts
|
|
79
|
+
var xdg = new XDG("vlt");
|
|
80
|
+
var delimiter = "~";
|
|
81
|
+
var manifestCacheMaxAge = 5 * 60 * 1e3;
|
|
82
|
+
var noRegistryError = (spec) => error(
|
|
83
|
+
'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',
|
|
84
|
+
{ code: "ECONFIG", spec }
|
|
85
|
+
);
|
|
86
|
+
var PackageInfoClient = class {
|
|
87
|
+
#registryClient;
|
|
88
|
+
#projectRoot;
|
|
89
|
+
#tarPool;
|
|
90
|
+
options;
|
|
91
|
+
#resolutions = /* @__PURE__ */ new Map();
|
|
92
|
+
packageJson;
|
|
93
|
+
monorepo;
|
|
94
|
+
#trustedIntegrities = /* @__PURE__ */ new Map();
|
|
95
|
+
#manifestCacheMinAge = Date.now() - manifestCacheMaxAge;
|
|
96
|
+
#cachePath;
|
|
97
|
+
// In-flight coalescing key is `${registry}${name}` — no representation
|
|
98
|
+
// component. Safe only because every caller requests the same full
|
|
99
|
+
// packument (see #fetchPackument).
|
|
100
|
+
#packumentPromises = /* @__PURE__ */ new Map();
|
|
101
|
+
// unique temp file names for atomic manifest cache writes
|
|
102
|
+
#manifestWriteRandom = randomBytes(6).toString("hex");
|
|
103
|
+
#manifestWriteCount = 0;
|
|
104
|
+
// cache paths already written this run. manifest() is called many
|
|
105
|
+
// times for the same cache key per install and content for a given
|
|
106
|
+
// path is deterministic within a run, so only the first write is
|
|
107
|
+
// needed. entries are removed when the on-disk file is invalidated
|
|
108
|
+
// so the refreshed manifest can be written again.
|
|
109
|
+
#manifestWritePaths = /* @__PURE__ */ new Set();
|
|
110
|
+
#registryClientPromise;
|
|
111
|
+
#tarPoolPromise;
|
|
112
|
+
async getRegistryClient() {
|
|
113
|
+
if (this.#registryClient) return this.#registryClient;
|
|
114
|
+
this.#registryClientPromise ??= import("./src-6OKPBJJT.js").then(({ RegistryClient }) => {
|
|
115
|
+
this.#registryClient = new RegistryClient(this.options);
|
|
116
|
+
return this.#registryClient;
|
|
117
|
+
});
|
|
118
|
+
return this.#registryClientPromise;
|
|
119
|
+
}
|
|
120
|
+
async getTarPool() {
|
|
121
|
+
if (this.#tarPool) return this.#tarPool;
|
|
122
|
+
this.#tarPoolPromise ??= import("./src-M5RRGKUM.js").then(
|
|
123
|
+
({ Pool }) => {
|
|
124
|
+
this.#tarPool = new Pool();
|
|
125
|
+
return this.#tarPool;
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
return this.#tarPoolPromise;
|
|
129
|
+
}
|
|
130
|
+
constructor(options = {}) {
|
|
131
|
+
this.options = options;
|
|
132
|
+
this.#projectRoot = options.projectRoot || process.cwd();
|
|
133
|
+
this.packageJson = options.packageJson ?? new PackageJson();
|
|
134
|
+
const wsLoad = {
|
|
135
|
+
...options.workspace?.length && { paths: options.workspace },
|
|
136
|
+
...options["workspace-group"]?.length && {
|
|
137
|
+
groups: options["workspace-group"]
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
this.monorepo = options.monorepo ?? Monorepo.maybeLoad(this.#projectRoot, {
|
|
141
|
+
load: wsLoad,
|
|
142
|
+
packageJson: this.packageJson
|
|
143
|
+
});
|
|
144
|
+
this.#cachePath = options.cache ?? xdg.cache();
|
|
145
|
+
void mkdir(pathResolve(this.#cachePath, "package-info"), {
|
|
146
|
+
recursive: true
|
|
147
|
+
}).catch(() => {
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async extract(spec, target, options = {}) {
|
|
151
|
+
if (typeof spec === "string")
|
|
152
|
+
spec = Spec.parse(spec, this.options);
|
|
153
|
+
const {
|
|
154
|
+
from = this.#projectRoot,
|
|
155
|
+
integrity,
|
|
156
|
+
resolved,
|
|
157
|
+
fromLockfile = false
|
|
158
|
+
} = options;
|
|
159
|
+
const f = spec.final;
|
|
160
|
+
const alreadyResolved = !!(integrity && resolved);
|
|
161
|
+
const r = alreadyResolved ? { resolved, integrity, spec } : await this.resolve(spec, options);
|
|
162
|
+
switch (f.type) {
|
|
163
|
+
case "git": {
|
|
164
|
+
const {
|
|
165
|
+
gitRemote,
|
|
166
|
+
gitCommittish,
|
|
167
|
+
remoteURL,
|
|
168
|
+
gitSelectorParsed
|
|
169
|
+
} = f;
|
|
170
|
+
if (!remoteURL) {
|
|
171
|
+
if (!gitRemote)
|
|
172
|
+
throw this.#resolveError(
|
|
173
|
+
spec,
|
|
174
|
+
options,
|
|
175
|
+
"no remote on git: specifier"
|
|
176
|
+
);
|
|
177
|
+
const { path } = gitSelectorParsed ?? {};
|
|
178
|
+
if (path !== void 0) {
|
|
179
|
+
const tmp = pathResolve(
|
|
180
|
+
dirname(target),
|
|
181
|
+
`.TEMP.${basename(target)}-${randomBytes(6).toString("hex")}`
|
|
182
|
+
);
|
|
183
|
+
await clone(gitRemote, gitCommittish, tmp, { spec });
|
|
184
|
+
const src = pathResolve(tmp, path);
|
|
185
|
+
await rename(src, target);
|
|
186
|
+
void rm2(tmp, { recursive: true, force: true });
|
|
187
|
+
} else {
|
|
188
|
+
await clone(gitRemote, gitCommittish, target, { spec });
|
|
189
|
+
void rm2(target + "/.git", { recursive: true });
|
|
190
|
+
}
|
|
191
|
+
return r;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
case "registry": {
|
|
195
|
+
const fetchTarball = async (useCache) => {
|
|
196
|
+
const trustIntegrity = this.#trustedIntegrities.get(r.resolved) === r.integrity;
|
|
197
|
+
const response = await (await this.getRegistryClient()).request(r.resolved, {
|
|
198
|
+
integrity: r.integrity,
|
|
199
|
+
trustIntegrity,
|
|
200
|
+
...useCache === false ? { useCache } : {}
|
|
201
|
+
});
|
|
202
|
+
if (response.statusCode !== 200) {
|
|
203
|
+
throw this.#resolveError(
|
|
204
|
+
spec,
|
|
205
|
+
options,
|
|
206
|
+
`Registry returned HTTP ${response.statusCode} when fetching the tarball for ${spec}. The resolved version may have been unpublished, or the registry may be misconfigured or unreachable.`,
|
|
207
|
+
{
|
|
208
|
+
url: r.resolved,
|
|
209
|
+
response
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (!trustIntegrity && response.checkIntegrity({ spec, url: resolved })) {
|
|
214
|
+
this.#trustedIntegrities.set(
|
|
215
|
+
r.resolved,
|
|
216
|
+
response.integrity
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
const buf2 = response.buffer();
|
|
220
|
+
if (r.integrity && !fromLockfile && !response.fromCache) {
|
|
221
|
+
const hash = createHash("sha512");
|
|
222
|
+
hash.update(buf2);
|
|
223
|
+
const computed = `sha512-${hash.digest("base64")}`;
|
|
224
|
+
if (computed !== r.integrity) {
|
|
225
|
+
throw error("Tarball integrity check failed", {
|
|
226
|
+
code: "EINTEGRITY",
|
|
227
|
+
spec,
|
|
228
|
+
url: r.resolved,
|
|
229
|
+
wanted: r.integrity,
|
|
230
|
+
found: computed
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return buf2;
|
|
235
|
+
};
|
|
236
|
+
let buf;
|
|
237
|
+
try {
|
|
238
|
+
buf = await fetchTarball();
|
|
239
|
+
} catch (er) {
|
|
240
|
+
if (er instanceof Error && "cause" in er && er.cause?.code === "EINTEGRITY") {
|
|
241
|
+
buf = await fetchTarball(false);
|
|
242
|
+
} else {
|
|
243
|
+
throw er;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
await (await this.getTarPool()).unpack(buf, target);
|
|
248
|
+
} catch (er) {
|
|
249
|
+
throw this.#resolveError(
|
|
250
|
+
spec,
|
|
251
|
+
options,
|
|
252
|
+
"tar unpack failed",
|
|
253
|
+
{ cause: er }
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
return r;
|
|
257
|
+
}
|
|
258
|
+
case "remote": {
|
|
259
|
+
const response = await (await this.getRegistryClient()).request(r.resolved);
|
|
260
|
+
if (response.statusCode !== 200) {
|
|
261
|
+
throw this.#resolveError(
|
|
262
|
+
spec,
|
|
263
|
+
options,
|
|
264
|
+
"failed to fetch remote tarball",
|
|
265
|
+
{
|
|
266
|
+
url: r.resolved,
|
|
267
|
+
response
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
const buf = response.buffer();
|
|
272
|
+
const computed = import_ssri.default.fromData(buf, { algorithms: ["sha512"] }).toString();
|
|
273
|
+
if (r.integrity && r.integrity !== computed) {
|
|
274
|
+
throw error("Integrity check failure", {
|
|
275
|
+
code: "EINTEGRITY",
|
|
276
|
+
spec,
|
|
277
|
+
url: r.resolved,
|
|
278
|
+
wanted: r.integrity,
|
|
279
|
+
found: computed
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
r.integrity = computed;
|
|
283
|
+
try {
|
|
284
|
+
await (await this.getTarPool()).unpack(buf, target);
|
|
285
|
+
} catch (er) {
|
|
286
|
+
throw this.#resolveError(
|
|
287
|
+
spec,
|
|
288
|
+
options,
|
|
289
|
+
"remote tar unpack failed",
|
|
290
|
+
{ cause: er }
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
return r;
|
|
294
|
+
}
|
|
295
|
+
case "file": {
|
|
296
|
+
const { file } = f;
|
|
297
|
+
if (file === void 0)
|
|
298
|
+
throw this.#resolveError(spec, options, "no file path");
|
|
299
|
+
const path = pathResolve(from, file);
|
|
300
|
+
const st = await stat(path);
|
|
301
|
+
if (st.isFile()) {
|
|
302
|
+
try {
|
|
303
|
+
await (await this.getTarPool()).unpack(await this.tarball(spec, options), target);
|
|
304
|
+
} catch (er) {
|
|
305
|
+
throw this.#resolveError(
|
|
306
|
+
spec,
|
|
307
|
+
options,
|
|
308
|
+
"tar unpack failed",
|
|
309
|
+
{ cause: er }
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
} else if (st.isDirectory()) {
|
|
313
|
+
const rel = relative(dirname(target), path);
|
|
314
|
+
await symlink(rel, target, "dir");
|
|
315
|
+
} else {
|
|
316
|
+
throw this.#resolveError(
|
|
317
|
+
spec,
|
|
318
|
+
options,
|
|
319
|
+
"file: specifier does not resolve to directory or tarball"
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
return r;
|
|
323
|
+
}
|
|
324
|
+
case "workspace": {
|
|
325
|
+
const ws = this.#getWS(spec, options);
|
|
326
|
+
const rel = relative(dirname(target), ws.fullpath);
|
|
327
|
+
await symlink(rel, target, "dir");
|
|
328
|
+
return r;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
#getWS(spec, options) {
|
|
333
|
+
const { workspace } = spec;
|
|
334
|
+
if (workspace === void 0)
|
|
335
|
+
throw this.#resolveError(spec, options, "no workspace ID");
|
|
336
|
+
if (!this.monorepo) {
|
|
337
|
+
throw this.#resolveError(
|
|
338
|
+
spec,
|
|
339
|
+
options,
|
|
340
|
+
"Not in a monorepo, cannot resolve workspace spec"
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
const ws = this.monorepo.get(workspace);
|
|
344
|
+
if (!ws) {
|
|
345
|
+
throw this.#resolveError(spec, options, "workspace not found", {
|
|
346
|
+
wanted: workspace
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
return ws;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Return the manifest cache key for a spec and the current options.
|
|
353
|
+
*/
|
|
354
|
+
#manifestCacheKey(spec, options) {
|
|
355
|
+
let extra = "";
|
|
356
|
+
if (options["node-version"]) {
|
|
357
|
+
extra += `${delimiter}node-version:${options["node-version"]}`;
|
|
358
|
+
}
|
|
359
|
+
if (options.os) {
|
|
360
|
+
extra += `${delimiter}os:${options.os}`;
|
|
361
|
+
}
|
|
362
|
+
if (options.arch) {
|
|
363
|
+
extra += `${delimiter}arch:${options.arch}`;
|
|
364
|
+
}
|
|
365
|
+
return encodeURIComponent(
|
|
366
|
+
`${spec.registry ?? ""}${delimiter}${spec}${extra}`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Conditionally return the path to the manifest cache file. The logic
|
|
371
|
+
* to determine if caching should be skipped aligns with `pickManifest`
|
|
372
|
+
* and is used to avoid caching manifest results that can be variable.
|
|
373
|
+
*/
|
|
374
|
+
_manifestCachePath(spec, options) {
|
|
375
|
+
if (options.before) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const f = spec.final;
|
|
379
|
+
if (f.distTag || f.range?.isAny) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
const key = this.#manifestCacheKey(f, options);
|
|
383
|
+
return pathResolve(this.#cachePath, "package-info", key);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Write a manifest cache file atomically (write to a temp file in
|
|
387
|
+
* the same directory, then rename over the destination) so that
|
|
388
|
+
* concurrent readers never observe a partially written manifest.
|
|
389
|
+
* Freshness is tracked via the resulting file's mtime.
|
|
390
|
+
*/
|
|
391
|
+
async #writeManifestCache(cachePath, json) {
|
|
392
|
+
const tmp = `${cachePath}.${this.#manifestWriteRandom}.${this.#manifestWriteCount++}`;
|
|
393
|
+
try {
|
|
394
|
+
try {
|
|
395
|
+
await writeFile(tmp, json, "utf8");
|
|
396
|
+
} catch (err) {
|
|
397
|
+
if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
|
|
398
|
+
throw err;
|
|
399
|
+
}
|
|
400
|
+
await mkdir(dirname(cachePath), { recursive: true });
|
|
401
|
+
await writeFile(tmp, json, "utf8");
|
|
402
|
+
}
|
|
403
|
+
await rename(tmp, cachePath);
|
|
404
|
+
} catch {
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
async tarball(spec, options = {}) {
|
|
408
|
+
if (typeof spec === "string")
|
|
409
|
+
spec = Spec.parse(spec, this.options);
|
|
410
|
+
const f = spec.final;
|
|
411
|
+
switch (f.type) {
|
|
412
|
+
case "registry": {
|
|
413
|
+
const { dist } = await this.manifest(spec, options);
|
|
414
|
+
if (!dist)
|
|
415
|
+
throw this.#resolveError(
|
|
416
|
+
spec,
|
|
417
|
+
options,
|
|
418
|
+
`The registry manifest for ${spec} has no "dist" section, so no tarball can be resolved. The package version may be malformed or unpublished.`
|
|
419
|
+
);
|
|
420
|
+
const { tarball, integrity } = dist;
|
|
421
|
+
if (!tarball) {
|
|
422
|
+
throw this.#resolveError(
|
|
423
|
+
spec,
|
|
424
|
+
options,
|
|
425
|
+
`The registry manifest for ${spec} is missing a tarball URL (dist.tarball). The package version may be malformed or unpublished in this registry.`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
const fetchTarball = async (useCache) => {
|
|
429
|
+
const trustIntegrity = this.#trustedIntegrities.get(tarball) === integrity;
|
|
430
|
+
const response = await (await this.getRegistryClient()).request(tarball, {
|
|
431
|
+
...options,
|
|
432
|
+
integrity,
|
|
433
|
+
trustIntegrity,
|
|
434
|
+
...useCache === false ? { useCache } : {}
|
|
435
|
+
});
|
|
436
|
+
if (response.statusCode !== 200) {
|
|
437
|
+
throw this.#resolveError(
|
|
438
|
+
spec,
|
|
439
|
+
options,
|
|
440
|
+
`Registry returned HTTP ${response.statusCode} when fetching the tarball for ${spec} at ${tarball}. The version may have been unpublished, or the registry may be misconfigured or unreachable.`,
|
|
441
|
+
{ response, url: tarball }
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
if (!trustIntegrity && response.checkIntegrity({ spec, url: tarball })) {
|
|
445
|
+
this.#trustedIntegrities.set(tarball, response.integrity);
|
|
446
|
+
}
|
|
447
|
+
const buf = response.buffer();
|
|
448
|
+
if (integrity && !response.fromCache) {
|
|
449
|
+
const hash = createHash("sha512");
|
|
450
|
+
hash.update(buf);
|
|
451
|
+
const computed = `sha512-${hash.digest("base64")}`;
|
|
452
|
+
if (computed !== integrity) {
|
|
453
|
+
throw error("Tarball integrity check failed", {
|
|
454
|
+
code: "EINTEGRITY",
|
|
455
|
+
spec,
|
|
456
|
+
url: tarball,
|
|
457
|
+
wanted: integrity,
|
|
458
|
+
found: computed
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return buf;
|
|
463
|
+
};
|
|
464
|
+
try {
|
|
465
|
+
return await fetchTarball();
|
|
466
|
+
} catch (er) {
|
|
467
|
+
if (er instanceof Error && "cause" in er && er.cause?.code === "EINTEGRITY") {
|
|
468
|
+
return await fetchTarball(false);
|
|
469
|
+
}
|
|
470
|
+
throw er;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
case "git": {
|
|
474
|
+
const {
|
|
475
|
+
remoteURL,
|
|
476
|
+
gitRemote,
|
|
477
|
+
gitCommittish,
|
|
478
|
+
gitSelectorParsed
|
|
479
|
+
} = f;
|
|
480
|
+
const s = spec;
|
|
481
|
+
if (!remoteURL) {
|
|
482
|
+
if (!gitRemote) {
|
|
483
|
+
throw this.#resolveError(
|
|
484
|
+
spec,
|
|
485
|
+
options,
|
|
486
|
+
"no remote on git: specifier"
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
const { path } = gitSelectorParsed ?? {};
|
|
490
|
+
return await this.#tmpdir(async (dir) => {
|
|
491
|
+
await clone(gitRemote, gitCommittish, dir + "/package", {
|
|
492
|
+
spec: s
|
|
493
|
+
});
|
|
494
|
+
let cwd = dir;
|
|
495
|
+
if (path !== void 0) {
|
|
496
|
+
const src = pathResolve(dir, "package", path);
|
|
497
|
+
cwd = dirname(src);
|
|
498
|
+
const pkg = pathResolve(cwd, "package");
|
|
499
|
+
if (src !== pkg) {
|
|
500
|
+
const rand = randomBytes(6).toString("hex");
|
|
501
|
+
await rename(pkg, pkg + rand).catch(() => {
|
|
502
|
+
});
|
|
503
|
+
await rename(src, pkg);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return Qn({ cwd, gzip: true }, ["package"]).concat();
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
case "remote": {
|
|
511
|
+
const { remoteURL } = f;
|
|
512
|
+
if (!remoteURL) {
|
|
513
|
+
throw this.#resolveError(spec, options);
|
|
514
|
+
}
|
|
515
|
+
const response = await (await this.getRegistryClient()).request(remoteURL);
|
|
516
|
+
if (response.statusCode !== 200) {
|
|
517
|
+
throw this.#resolveError(
|
|
518
|
+
spec,
|
|
519
|
+
options,
|
|
520
|
+
"failed to fetch URL",
|
|
521
|
+
{ response, url: remoteURL }
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
return response.buffer();
|
|
525
|
+
}
|
|
526
|
+
case "file": {
|
|
527
|
+
const { file } = f;
|
|
528
|
+
if (file === void 0)
|
|
529
|
+
throw this.#resolveError(spec, options, "no file path");
|
|
530
|
+
const { from = this.#projectRoot } = options;
|
|
531
|
+
const path = pathResolve(from, file);
|
|
532
|
+
const st = await stat(path);
|
|
533
|
+
if (st.isDirectory()) {
|
|
534
|
+
const p = dirname(path);
|
|
535
|
+
const b = basename(path);
|
|
536
|
+
return Qn({ cwd: p, gzip: true }, [b]).concat();
|
|
537
|
+
}
|
|
538
|
+
return readFile(path);
|
|
539
|
+
}
|
|
540
|
+
case "workspace": {
|
|
541
|
+
const ws = this.#getWS(spec, options);
|
|
542
|
+
const p = dirname(ws.fullpath);
|
|
543
|
+
const b = basename(ws.fullpath);
|
|
544
|
+
return Qn({ cwd: p, gzip: true }, [b]).concat();
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
async manifest(spec, options = {}) {
|
|
549
|
+
const { from = this.#projectRoot } = options;
|
|
550
|
+
if (typeof spec === "string")
|
|
551
|
+
spec = Spec.parse(spec, this.options);
|
|
552
|
+
const f = spec.final;
|
|
553
|
+
switch (f.type) {
|
|
554
|
+
case "registry": {
|
|
555
|
+
const cachePath = this._manifestCachePath(spec, options);
|
|
556
|
+
if (cachePath) {
|
|
557
|
+
try {
|
|
558
|
+
const [st, cached] = await Promise.all([
|
|
559
|
+
stat(cachePath),
|
|
560
|
+
readFile(cachePath, "utf8")
|
|
561
|
+
]);
|
|
562
|
+
const json = JSON.parse(cached);
|
|
563
|
+
if (st.mtimeMs < this.#manifestCacheMinAge || json.__VLT_MANIFEST_CACHE_TIMESTAMP !== void 0) {
|
|
564
|
+
this.#manifestWritePaths.delete(cachePath);
|
|
565
|
+
void unlink(cachePath).catch(() => {
|
|
566
|
+
});
|
|
567
|
+
throw new Error("manifest cache expired");
|
|
568
|
+
}
|
|
569
|
+
return json;
|
|
570
|
+
} catch {
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
const mani = pickManifest(
|
|
574
|
+
await this.packument(f, options),
|
|
575
|
+
spec,
|
|
576
|
+
options
|
|
577
|
+
);
|
|
578
|
+
if (!mani) throw this.#resolveError(spec, options);
|
|
579
|
+
if (cachePath && !this.#manifestWritePaths.has(cachePath)) {
|
|
580
|
+
this.#manifestWritePaths.add(cachePath);
|
|
581
|
+
void this.#writeManifestCache(
|
|
582
|
+
cachePath,
|
|
583
|
+
JSON.stringify(mani)
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
return mani;
|
|
587
|
+
}
|
|
588
|
+
case "git": {
|
|
589
|
+
const {
|
|
590
|
+
gitRemote,
|
|
591
|
+
gitCommittish,
|
|
592
|
+
remoteURL,
|
|
593
|
+
gitSelectorParsed
|
|
594
|
+
} = f;
|
|
595
|
+
if (!remoteURL) {
|
|
596
|
+
const s = spec;
|
|
597
|
+
if (!gitRemote)
|
|
598
|
+
throw this.#resolveError(spec, options, "no git remote");
|
|
599
|
+
return await this.#tmpdir(async (dir) => {
|
|
600
|
+
await clone(gitRemote, gitCommittish, dir, { spec: s });
|
|
601
|
+
const { path } = gitSelectorParsed ?? {};
|
|
602
|
+
const pkgDir = path !== void 0 ? pathResolve(dir, path) : dir;
|
|
603
|
+
return this.#readExtracted(pkgDir, s, options);
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
case "remote": {
|
|
608
|
+
const { remoteURL } = f;
|
|
609
|
+
if (!remoteURL) {
|
|
610
|
+
throw this.#resolveError(
|
|
611
|
+
spec,
|
|
612
|
+
options,
|
|
613
|
+
"no remoteURL on remote specifier"
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
const s = spec;
|
|
617
|
+
return await this.#tmpdir(async (dir) => {
|
|
618
|
+
const response = await (await this.getRegistryClient()).request(remoteURL);
|
|
619
|
+
if (response.statusCode !== 200) {
|
|
620
|
+
throw this.#resolveError(
|
|
621
|
+
s,
|
|
622
|
+
options,
|
|
623
|
+
"failed to fetch URL",
|
|
624
|
+
{ response, url: remoteURL }
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
const buf = response.buffer();
|
|
628
|
+
const computed = import_ssri.default.fromData(buf, { algorithms: ["sha512"] }).toString();
|
|
629
|
+
try {
|
|
630
|
+
await (await this.getTarPool()).unpack(buf, dir);
|
|
631
|
+
} catch (er) {
|
|
632
|
+
throw this.#resolveError(
|
|
633
|
+
s,
|
|
634
|
+
options,
|
|
635
|
+
"tar unpack failed",
|
|
636
|
+
{ cause: er }
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
const mani = this.#readExtracted(dir, s, options);
|
|
640
|
+
mani.dist = { integrity: computed };
|
|
641
|
+
return mani;
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
case "file": {
|
|
645
|
+
const { file } = f;
|
|
646
|
+
if (file === void 0)
|
|
647
|
+
throw this.#resolveError(spec, options, "no file path");
|
|
648
|
+
const path = pathResolve(from, file);
|
|
649
|
+
const st = await stat(path);
|
|
650
|
+
if (st.isDirectory()) {
|
|
651
|
+
return this.packageJson.read(path);
|
|
652
|
+
}
|
|
653
|
+
const s = spec;
|
|
654
|
+
return await this.#tmpdir(async (dir) => {
|
|
655
|
+
try {
|
|
656
|
+
await (await this.getTarPool()).unpack(await readFile(path), dir);
|
|
657
|
+
} catch (er) {
|
|
658
|
+
throw this.#resolveError(
|
|
659
|
+
s,
|
|
660
|
+
options,
|
|
661
|
+
"tar unpack failed",
|
|
662
|
+
{ cause: er }
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
return this.#readExtracted(dir, s, options);
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
case "workspace": {
|
|
669
|
+
return this.#getWS(spec, options).manifest;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
async packument(spec, options = {}) {
|
|
674
|
+
if (typeof spec === "string")
|
|
675
|
+
spec = Spec.parse(spec, this.options);
|
|
676
|
+
const f = spec.final;
|
|
677
|
+
switch (f.type) {
|
|
678
|
+
// RevDoc is the equivalent of a packument for a git repo
|
|
679
|
+
case "git": {
|
|
680
|
+
const { gitRemote } = f;
|
|
681
|
+
if (!gitRemote) {
|
|
682
|
+
throw this.#resolveError(
|
|
683
|
+
spec,
|
|
684
|
+
options,
|
|
685
|
+
"git remote could not be determined"
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
const revDoc = await revs(gitRemote, {
|
|
689
|
+
cwd: this.options.projectRoot
|
|
690
|
+
});
|
|
691
|
+
if (!revDoc) throw this.#resolveError(spec, options);
|
|
692
|
+
return asPackument(revDoc);
|
|
693
|
+
}
|
|
694
|
+
// these are all faked packuments
|
|
695
|
+
case "file":
|
|
696
|
+
case "workspace":
|
|
697
|
+
case "remote": {
|
|
698
|
+
const manifest = await this.manifest(f, options);
|
|
699
|
+
return {
|
|
700
|
+
name: manifest.name ?? "",
|
|
701
|
+
"dist-tags": {
|
|
702
|
+
latest: manifest.version ?? ""
|
|
703
|
+
},
|
|
704
|
+
versions: {
|
|
705
|
+
[manifest.version ?? ""]: manifest
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
case "registry": {
|
|
710
|
+
const { registry, name } = f;
|
|
711
|
+
if (!registry) throw noRegistryError(spec);
|
|
712
|
+
const packumentKey = `${registry}${name}`;
|
|
713
|
+
const inflight = this.#packumentPromises.get(packumentKey);
|
|
714
|
+
if (inflight) return inflight;
|
|
715
|
+
const pakuURL = new URL(name, registry);
|
|
716
|
+
const promise = this.#fetchPackument(spec, options, pakuURL);
|
|
717
|
+
this.#packumentPromises.set(packumentKey, promise);
|
|
718
|
+
promise.then(
|
|
719
|
+
() => this.#packumentPromises.delete(packumentKey),
|
|
720
|
+
() => this.#packumentPromises.delete(packumentKey)
|
|
721
|
+
);
|
|
722
|
+
return promise;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
async #fetchPackument(spec, options, pakuURL, useCache) {
|
|
727
|
+
const response = await (await this.getRegistryClient()).request(pakuURL, {
|
|
728
|
+
headers: { accept: "application/json" },
|
|
729
|
+
...useCache === false ? { useCache } : {}
|
|
730
|
+
});
|
|
731
|
+
if (response.statusCode !== 200) {
|
|
732
|
+
throw this.#resolveError(
|
|
733
|
+
spec,
|
|
734
|
+
options,
|
|
735
|
+
"failed to fetch packument",
|
|
736
|
+
{
|
|
737
|
+
url: pakuURL,
|
|
738
|
+
response
|
|
739
|
+
}
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
try {
|
|
743
|
+
return response.json();
|
|
744
|
+
} catch (er) {
|
|
745
|
+
if (useCache !== false) {
|
|
746
|
+
return this.#fetchPackument(spec, options, pakuURL, false);
|
|
747
|
+
}
|
|
748
|
+
throw er;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
async resolve(spec, options = {}) {
|
|
752
|
+
const memoKey = String(spec);
|
|
753
|
+
if (typeof spec === "string")
|
|
754
|
+
spec = Spec.parse(spec, this.options);
|
|
755
|
+
const memo = this.#resolutions.get(memoKey);
|
|
756
|
+
if (memo) return memo;
|
|
757
|
+
const f = spec.final;
|
|
758
|
+
switch (f.type) {
|
|
759
|
+
case "file": {
|
|
760
|
+
const { file } = f;
|
|
761
|
+
if (!file || !f.file) {
|
|
762
|
+
throw this.#resolveError(
|
|
763
|
+
spec,
|
|
764
|
+
options,
|
|
765
|
+
"no path on file: specifier"
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
const { from = this.#projectRoot } = options;
|
|
769
|
+
const resolved = pathResolve(from, f.file);
|
|
770
|
+
const r = { resolved, spec };
|
|
771
|
+
this.#resolutions.set(memoKey, r);
|
|
772
|
+
return r;
|
|
773
|
+
}
|
|
774
|
+
case "remote": {
|
|
775
|
+
const { remoteURL } = f;
|
|
776
|
+
if (!remoteURL)
|
|
777
|
+
throw this.#resolveError(
|
|
778
|
+
spec,
|
|
779
|
+
options,
|
|
780
|
+
"no URL in remote specifier"
|
|
781
|
+
);
|
|
782
|
+
const r = { resolved: remoteURL, spec };
|
|
783
|
+
this.#resolutions.set(memoKey, r);
|
|
784
|
+
return r;
|
|
785
|
+
}
|
|
786
|
+
case "workspace": {
|
|
787
|
+
const ws = this.#getWS(spec, options);
|
|
788
|
+
return {
|
|
789
|
+
resolved: ws.fullpath,
|
|
790
|
+
spec
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
case "registry": {
|
|
794
|
+
const mani = await this.manifest(spec, options);
|
|
795
|
+
if (mani.dist) {
|
|
796
|
+
const { integrity, tarball, signatures } = mani.dist;
|
|
797
|
+
if (tarball) {
|
|
798
|
+
const r = {
|
|
799
|
+
resolved: tarball,
|
|
800
|
+
integrity,
|
|
801
|
+
signatures,
|
|
802
|
+
spec
|
|
803
|
+
};
|
|
804
|
+
this.#resolutions.set(memoKey, r);
|
|
805
|
+
return r;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
throw this.#resolveError(spec, options);
|
|
809
|
+
}
|
|
810
|
+
case "git": {
|
|
811
|
+
const { gitRemote, remoteURL, gitSelectorParsed } = f;
|
|
812
|
+
if (remoteURL && gitSelectorParsed?.path === void 0) {
|
|
813
|
+
const r = { resolved: remoteURL, spec };
|
|
814
|
+
this.#resolutions.set(memoKey, r);
|
|
815
|
+
return r;
|
|
816
|
+
}
|
|
817
|
+
if (!gitRemote) {
|
|
818
|
+
throw this.#resolveError(
|
|
819
|
+
spec,
|
|
820
|
+
options,
|
|
821
|
+
"no remote on git specifier"
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
const rev = await resolve(gitRemote, f.gitCommittish, {
|
|
825
|
+
spec
|
|
826
|
+
});
|
|
827
|
+
if (rev) {
|
|
828
|
+
const r = {
|
|
829
|
+
resolved: `${gitRemote}#${rev.sha}`,
|
|
830
|
+
spec
|
|
831
|
+
};
|
|
832
|
+
if (gitSelectorParsed) {
|
|
833
|
+
r.resolved += Object.entries(gitSelectorParsed).filter(([_, v]) => v).map(([k, v]) => `::${k}:${v}`).join("");
|
|
834
|
+
}
|
|
835
|
+
this.#resolutions.set(memoKey, r);
|
|
836
|
+
return r;
|
|
837
|
+
}
|
|
838
|
+
const s = spec;
|
|
839
|
+
return this.#tmpdir(async (tmpdir) => {
|
|
840
|
+
const sha = await clone(
|
|
841
|
+
gitRemote,
|
|
842
|
+
s.gitCommittish,
|
|
843
|
+
tmpdir,
|
|
844
|
+
{
|
|
845
|
+
spec: s
|
|
846
|
+
}
|
|
847
|
+
);
|
|
848
|
+
const r = {
|
|
849
|
+
resolved: `${gitRemote}#${sha}`,
|
|
850
|
+
spec: s
|
|
851
|
+
};
|
|
852
|
+
this.#resolutions.set(memoKey, r);
|
|
853
|
+
return r;
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Read the manifest out of a directory we cloned or unpacked. Failures are
|
|
860
|
+
* labeled with the spec, because the internal directory says nothing about
|
|
861
|
+
* which dependency is at fault.
|
|
862
|
+
*/
|
|
863
|
+
#readExtracted(dir, spec, options) {
|
|
864
|
+
try {
|
|
865
|
+
return this.packageJson.read(dir);
|
|
866
|
+
} catch (er) {
|
|
867
|
+
throw this.#resolveError(
|
|
868
|
+
spec,
|
|
869
|
+
options,
|
|
870
|
+
"invalid package manifest",
|
|
871
|
+
{ cause: er }
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
async #tmpdir(fn) {
|
|
876
|
+
const p = `package-info/${randomBytes(6).toString("hex")}`;
|
|
877
|
+
const dir = xdg.runtime(p);
|
|
878
|
+
try {
|
|
879
|
+
return await fn(dir);
|
|
880
|
+
} finally {
|
|
881
|
+
void rm2(dir, { recursive: true, force: true });
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
// error resolving
|
|
885
|
+
#resolveError(spec, options = {}, message = "Could not resolve", extra = {}) {
|
|
886
|
+
const { from = this.#projectRoot } = options;
|
|
887
|
+
const er = error(
|
|
888
|
+
message,
|
|
889
|
+
{
|
|
890
|
+
code: "ERESOLVE",
|
|
891
|
+
spec,
|
|
892
|
+
from,
|
|
893
|
+
...extra
|
|
894
|
+
},
|
|
895
|
+
this.#resolveError
|
|
896
|
+
);
|
|
897
|
+
return er;
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
export {
|
|
902
|
+
PackageInfoClient
|
|
903
|
+
};
|