@vltpkg/cli-js 1.4.0 → 1.6.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.
Files changed (105) hide show
  1. package/{access-422UGEWN.js → access-AJ654YKY.js} +13 -12
  2. package/{bugs-RED7Y33Q.js → bugs-N73DVYHD.js} +32 -25
  3. package/{build-IHMPBWRO.js → build-VZ3EZKMM.js} +65 -21
  4. package/{cache-FJP2RZJX.js → cache-VROEWG2C.js} +20 -17
  5. package/cache-unzip-src-unzip.js +58 -15
  6. package/{chunk-TPRK6IDA.js → chunk-22LZBDEC.js} +2 -2
  7. package/chunk-36UIE654.js +6248 -0
  8. package/{chunk-UGCKF5ZE.js → chunk-3JIN46K5.js} +1 -1
  9. package/{chunk-OAJ3PO3Z.js → chunk-44AWMA4F.js} +25 -13
  10. package/chunk-4E65BBTM.js +77 -0
  11. package/{chunk-SR2VOY5J.js → chunk-4GMNWW4C.js} +1 -1
  12. package/{chunk-5IJTPZXP.js → chunk-6D3QAFNZ.js} +1 -1
  13. package/{chunk-X4FVR4R5.js → chunk-75HGJVNG.js} +12 -10
  14. package/{chunk-THSYN5EK.js → chunk-7M2VTFLP.js} +12 -1
  15. package/{chunk-2AMOC4DN.js → chunk-ANW36H4T.js} +4 -4
  16. package/chunk-B6RIGNEO.js +626 -0
  17. package/{chunk-FLH4YC6W.js → chunk-BF5DRGRZ.js} +60 -15
  18. package/chunk-BH5CVXNY.js +115 -0
  19. package/{chunk-PLG3OYCX.js → chunk-CAV7FKWQ.js} +3 -2
  20. package/{chunk-C23TDXRG.js → chunk-CYK6I4M6.js} +1 -1
  21. package/chunk-DXED4ARV.js +436 -0
  22. package/chunk-E74WGW5C.js +49 -0
  23. package/{chunk-WF6KLKRN.js → chunk-EFHOWRKU.js} +103 -1
  24. package/chunk-EMTGRCSE.js +1111 -0
  25. package/{chunk-5Y4SYLJ2.js → chunk-EYGOEAJM.js} +1 -1
  26. package/{chunk-OVPHE4O7.js → chunk-F5LZMLAQ.js} +5335 -10902
  27. package/{chunk-HZXJ423P.js → chunk-FXD3IV2S.js} +4 -2
  28. package/chunk-GCTREKA4.js +115 -0
  29. package/{chunk-ZJMJ7MCT.js → chunk-GEQFMH5M.js} +1 -1
  30. package/{chunk-ISE4IRHF.js → chunk-GZVI75KX.js} +7 -14
  31. package/chunk-HOF7LEIC.js +24 -0
  32. package/{chunk-LHPEBLOU.js → chunk-HT6FS4VB.js} +1 -1
  33. package/{chunk-PHJJPY5G.js → chunk-IXAMCWIT.js} +5 -5
  34. package/{chunk-ASLX43R3.js → chunk-JCNI6ZHH.js} +7 -5
  35. package/chunk-JV5XR5JQ.js +349 -0
  36. package/{chunk-7T3XAYP4.js → chunk-KD5ZK72K.js} +1 -1
  37. package/{chunk-FZUYGJZU.js → chunk-KVWGMSPW.js} +137 -19
  38. package/{chunk-TO23PR7J.js → chunk-LCLRP64K.js} +14 -12
  39. package/{chunk-QCSUWACA.js → chunk-LGQVZTYR.js} +8 -36
  40. package/{chunk-5RHABCYI.js → chunk-LP3ORD3D.js} +143 -17
  41. package/chunk-MCDLJZXT.js +82 -0
  42. package/{chunk-DNRR3XMG.js → chunk-N6HV7JWC.js} +1 -1
  43. package/chunk-O6MQ7NN6.js +1155 -0
  44. package/{chunk-GIIAODRI.js → chunk-PC2HOBAQ.js} +7 -5
  45. package/{chunk-APMYKJI2.js → chunk-QNHBAGXQ.js} +1 -1
  46. package/chunk-RBQO54TG.js +59 -0
  47. package/chunk-SUU2WETN.js +268 -0
  48. package/{chunk-I7UMHYZX.js → chunk-TQQO2F56.js} +113 -1187
  49. package/{chunk-4UCADW6S.js → chunk-TWDSXQPN.js} +9 -7
  50. package/{chunk-MKWPTN3C.js → chunk-VLVMLSIF.js} +2 -2
  51. package/chunk-W4T5CGCO.js +52 -0
  52. package/{chunk-5TNXLRW2.js → chunk-YTDABXPD.js} +50 -12
  53. package/{ci-YSKNNO5M.js → ci-3BVMVQIT.js} +35 -13
  54. package/cli-package.json +3 -1
  55. package/{config-HO7GY3QT.js → config-2KQV7N5A.js} +16 -13
  56. package/{config-CSPCDMR3.js → config-EKHBW6I5.js} +12 -9
  57. package/{create-2TJT3AHJ.js → create-QVHNOIV3.js} +35 -29
  58. package/{deprecate-7FRJI2RL.js → deprecate-E254QBH6.js} +17 -15
  59. package/{dist-tag-WCFF5OEG.js → dist-tag-SITRFD7O.js} +13 -12
  60. package/{docs-JMBPTU23.js → docs-IDL2P7CA.js} +32 -25
  61. package/{exec-FBOUKZZ2.js → exec-7BK2W2WL.js} +35 -29
  62. package/{exec-cache-X3ZWM5S3.js → exec-cache-VY46L7DR.js} +27 -21
  63. package/{exec-local-Y3KQC22N.js → exec-local-D7R5T3DF.js} +26 -20
  64. package/{help-PUKVH5X7.js → help-RMRIEJQL.js} +6 -5
  65. package/{init-GOKAQXXZ.js → init-BGW4HJ6V.js} +15 -11
  66. package/{install-XFN4UFOC.js → install-U5GATZ2N.js} +144 -49
  67. package/{list-43JFFG5D.js → list-3VG4M2XL.js} +41 -28
  68. package/{login-RSTZKNKN.js → login-PHQWI6S6.js} +19 -16
  69. package/{logout-4576FFXZ.js → logout-DJCOGRFF.js} +13 -12
  70. package/{outdated-ACQ5A2Y7.js → outdated-JH3O6R3Y.js} +27 -22
  71. package/{pack-QQVJ3G25.js → pack-U5W5YWHK.js} +23 -18
  72. package/package.json +1 -1
  73. package/{ping-QCDQQRO5.js → ping-EKX43AOW.js} +13 -12
  74. package/{pkg-CSOJV7UC.js → pkg-SW5GMERT.js} +19 -14
  75. package/{profile-VL4HPW3N.js → profile-UGDRDMQ6.js} +13 -12
  76. package/{publish-2YBO6ZXE.js → publish-HTWKK3NN.js} +60 -45
  77. package/{query-IHHFMJRT.js → query-YE3FUVGG.js} +43 -30
  78. package/{registry-W7BRZZZ2.js → registry-ZGGWVLBM.js} +7 -7
  79. package/registry-client-src-revalidate.js +76 -22
  80. package/{repo-L3BXAAWS.js → repo-WDOCU6SE.js} +32 -25
  81. package/{reporter-5NYOHBO7.js → reporter-N5PAXB26.js} +121 -17
  82. package/{run-AMUUVLTI.js → run-IPARVIIQ.js} +26 -20
  83. package/{run-exec-5W3XWQZA.js → run-exec-C4RTREEW.js} +26 -20
  84. package/security-archive-src-update-expired.js +66 -21
  85. package/{setup-TFM4GJF7.js → setup-SYYUEHZL.js} +212 -32
  86. package/skills-KA2VR5Q5.js +480 -0
  87. package/skills-UBBMSBDQ.js +416 -0
  88. package/{src-4CYCUWZL.js → src-FUSTSM4J.js} +33 -22
  89. package/{src-I3GMULFP.js → src-QO5G2S4O.js} +11 -8
  90. package/{src-LUTN2ODD.js → src-W2VQULRG.js} +2 -2
  91. package/{token-OANOBE3G.js → token-UQNABECH.js} +15 -13
  92. package/{uninstall-YXTQ4AIZ.js → uninstall-FHBJ3OUV.js} +59 -18
  93. package/{unpublish-SZXYMYIU.js → unpublish-APJTEUBA.js} +31 -16
  94. package/{update-FHLMWGIM.js → update-NWZTL4S7.js} +52 -25
  95. package/{version-ZWFCTU5V.js → version-EMKKTL77.js} +20 -14
  96. package/{view-NFNJXMLV.js → view-BUUI33RV.js} +17 -15
  97. package/vlr.js +1 -1
  98. package/vlrx.js +1 -1
  99. package/vlt.js +1 -1
  100. package/vlx.js +1 -1
  101. package/vlxl.js +1 -1
  102. package/{whoami-O7GOSGCI.js → whoami-F6BSXGQ2.js} +13 -12
  103. package/chunk-G2YT2GWF.js +0 -120
  104. package/chunk-T6FBP4OU.js +0 -76
  105. package/chunk-U7TEQCBN.js +0 -880
@@ -0,0 +1,1155 @@
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
+ detectShell,
14
+ fishPath,
15
+ posixPath,
16
+ prettyPath,
17
+ shellPathCommand,
18
+ shellRcFile
19
+ } from "./chunk-BH5CVXNY.js";
20
+ import {
21
+ RollbackRemove,
22
+ cmdShimIfExists,
23
+ findCmdShimIfExists
24
+ } from "./chunk-JV5XR5JQ.js";
25
+ import {
26
+ readGlobalState,
27
+ updateGlobalState,
28
+ writeFileAtomic,
29
+ writeJsonAtomic
30
+ } from "./chunk-GCTREKA4.js";
31
+ import {
32
+ globalBinDir,
33
+ globalWorkspaceName,
34
+ globalWorkspacePath,
35
+ globalWorkspacesDir,
36
+ isInside,
37
+ samePath
38
+ } from "./chunk-MCDLJZXT.js";
39
+ import {
40
+ parseSpecArg
41
+ } from "./chunk-7M2VTFLP.js";
42
+ import {
43
+ joinDepIDTuple
44
+ } from "./chunk-CAV7FKWQ.js";
45
+ import {
46
+ Spec
47
+ } from "./chunk-6D3QAFNZ.js";
48
+ import {
49
+ promiseSpawn,
50
+ which
51
+ } from "./chunk-SUU2WETN.js";
52
+ import {
53
+ XDG
54
+ } from "./chunk-XNLSTHDK.js";
55
+ import {
56
+ asError,
57
+ isObject
58
+ } from "./chunk-BF5DRGRZ.js";
59
+ import {
60
+ error
61
+ } from "./chunk-WZWDS3W4.js";
62
+
63
+ // ../../src/cli-sdk/src/shell-setup/windows.ts
64
+ import { mkdtemp, readFile, rm } from "node:fs/promises";
65
+ import { tmpdir } from "node:os";
66
+ import { join, win32 } from "node:path";
67
+ var userEnvKey = "HKCU\\Environment";
68
+ var userEnvLabel = "your Windows user environment";
69
+ var editPathHint = 'Start > "Edit environment variables for your account" > Path';
70
+ var refreshVar = "VLT_PATH_REFRESH";
71
+ var system32 = (env) => win32.join(
72
+ [env.SystemRoot, env.windir].find(
73
+ (d) => d && win32.isAbsolute(d)
74
+ ) ?? "C:\\Windows",
75
+ "System32"
76
+ );
77
+ var run = (env, exe, args) => promiseSpawn(win32.join(system32(env), exe), args, {
78
+ stdio: ["ignore", "pipe", "pipe"],
79
+ windowsHide: true
80
+ });
81
+ var detail = (er) => {
82
+ const e = asError(er);
83
+ const c = e.cause;
84
+ return typeof c?.stderr === "string" && c.stderr ? c.stderr : c?.cause ? asError(c.cause).message : e.message;
85
+ };
86
+ var fail = (what, key, why, hint, cause) => error(
87
+ `Could not ${what} your user Path (${key}): ${why}
88
+ ${hint}`,
89
+ {
90
+ code: "ECONFIG",
91
+ cause
92
+ }
93
+ );
94
+ var addIt = (dir) => `Add ${dir} yourself: ${editPathHint}`;
95
+ var norm = (p, env) => win32.normalize(expandEnv(p.trim().replace(/^"(.*)"$/, "$1"), env)).replace(/[\\/]+$/, "").toLowerCase();
96
+ var unesc = (s) => s.replace(/\\([\s\S])/g, "$1");
97
+ var parseRegExport = (text, name) => {
98
+ const lines = text.replace(/,\\\r?\n */g, ",").split(/\r?\n/);
99
+ let inKey = false;
100
+ for (const line of lines) {
101
+ if (line.startsWith("[")) {
102
+ if (inKey) return void 0;
103
+ inKey = true;
104
+ continue;
105
+ }
106
+ const [, n = "", v = ""] = /^"((?:[^"\\]|\\[\s\S])*)"=([\s\S]*)$/.exec(line) ?? [];
107
+ if (!inKey || unesc(n).toLowerCase() !== name.toLowerCase()) {
108
+ continue;
109
+ }
110
+ const [, sz] = /^"((?:[^"\\]|\\[\s\S])*)"$/.exec(v) ?? [];
111
+ if (sz !== void 0) return { type: "REG_SZ", data: unesc(sz) };
112
+ const [, hex] = /^hex\(2\):([\da-f,]*)$/i.exec(v) ?? [];
113
+ if (hex !== void 0) {
114
+ const bytes2 = hex.split(",").filter(Boolean).map((h) => parseInt(h, 16));
115
+ return {
116
+ type: "REG_EXPAND_SZ",
117
+ data: Buffer.from(bytes2).toString("utf16le").replace(/\0+$/, "")
118
+ };
119
+ }
120
+ return { type: v.replace(/:[\s\S]*$/, ""), data: "" };
121
+ }
122
+ return void 0;
123
+ };
124
+ var expandEnv = (s, env = process.env) => s.replace(
125
+ /%([^%]+)%/g,
126
+ (m, n) => Object.entries(env).find(
127
+ ([k]) => k.toLowerCase() === n.toLowerCase()
128
+ )?.[1] ?? m
129
+ );
130
+ var addPathEntry = (value, dir, env = process.env) => {
131
+ if (!value) return { action: "create", data: dir };
132
+ const previous = value.data;
133
+ const d = norm(dir, env);
134
+ if (previous.split(";").some((e) => e.trim() && norm(e, env) === d)) {
135
+ return { action: "unchanged", previous, data: previous };
136
+ }
137
+ return {
138
+ action: "prepend",
139
+ previous,
140
+ data: previous ? `${dir};${previous}` : dir
141
+ };
142
+ };
143
+ var readUserPath = async ({
144
+ env = process.env,
145
+ key = userEnvKey
146
+ } = {}) => {
147
+ const d = await mkdtemp(join(tmpdir(), "vlt-"));
148
+ const file = join(d, "env.reg");
149
+ try {
150
+ await run(env, "reg.exe", ["export", key, file, "/y"]);
151
+ const v = parseRegExport(
152
+ (await readFile(file)).toString("utf16le"),
153
+ "Path"
154
+ );
155
+ if (v && /[\p{Cs}\0]/u.test(v.data)) {
156
+ throw new Error("it has characters vlt could not read");
157
+ }
158
+ return v;
159
+ } finally {
160
+ await rm(d, {
161
+ recursive: true,
162
+ force: true,
163
+ maxRetries: 3
164
+ }).catch(() => {
165
+ });
166
+ }
167
+ };
168
+ var planWindowsPath = async (dir, { env = process.env, key = userEnvKey } = {}) => {
169
+ if (/[;%]/.test(dir)) {
170
+ throw fail(
171
+ "update",
172
+ key,
173
+ `the folder name has ";" or "%"`,
174
+ "Set --global-bin-dir to a folder without them"
175
+ );
176
+ }
177
+ const value = await readUserPath({ env, key }).catch(
178
+ (er) => {
179
+ throw fail("read", key, detail(er), addIt(dir), er);
180
+ }
181
+ );
182
+ if (value && !/^REG_(EXPAND_)?SZ$/.test(value.type)) {
183
+ throw fail(
184
+ "update",
185
+ key,
186
+ `unexpected value type ${value.type}`,
187
+ addIt(dir)
188
+ );
189
+ }
190
+ return { key, dir, ...addPathEntry(value, dir, env) };
191
+ };
192
+ var applyWindowsPath = async (c, { env = process.env } = {}) => {
193
+ await run(env, "reg.exe", [
194
+ "add",
195
+ c.key,
196
+ "/v",
197
+ "Path",
198
+ "/t",
199
+ "REG_EXPAND_SZ",
200
+ "/d",
201
+ c.data,
202
+ "/f"
203
+ ]).catch((er) => {
204
+ throw fail("update", c.key, detail(er), addIt(c.dir), er);
205
+ });
206
+ if (c.key !== userEnvKey) return;
207
+ await run(env, "setx.exe", [refreshVar, "1"]).then(
208
+ () => run(env, "reg.exe", ["delete", c.key, "/v", refreshVar, "/f"])
209
+ ).catch(() => {
210
+ });
211
+ };
212
+
213
+ // ../../src/cli-sdk/src/shell-setup/index.ts
214
+ import { existsSync as existsSync2 } from "node:fs";
215
+ import { chown, mkdir, realpath as realpath2, writeFile } from "node:fs/promises";
216
+ import { basename, dirname as dirname2, resolve as resolve3 } from "node:path";
217
+ import { createInterface } from "node:readline/promises";
218
+
219
+ // ../../src/cli-sdk/src/shell-setup/env.ts
220
+ import { resolve } from "node:path";
221
+ var envFile = (globalDir) => resolve(globalDir, "env");
222
+ var envFishFile = (globalDir) => resolve(globalDir, "env.fish");
223
+ var renderEnv = (dir, o = {}) => [
224
+ "# vlt global bin dir; sourced from the shell rc file. Edit with `vlt setup --path`.",
225
+ 'case ":$PATH:" in',
226
+ ` *:${posixPath(dir, o)}:*) ;;`,
227
+ ` *) ${shellPathCommand("sh", dir, o)} ;;`,
228
+ "esac",
229
+ ""
230
+ ].join("\n");
231
+ var renderEnvFish = (dir, o = {}) => {
232
+ const d = fishPath(dir, o);
233
+ return [
234
+ "# vlt global bin dir; sourced from fish config. Edit with `vlt setup --path`.",
235
+ // session only, and fish_add_path needs fish 3.2
236
+ `contains -- ${d} $PATH; or set -gx PATH ${d} $PATH`,
237
+ ""
238
+ ].join("\n");
239
+ };
240
+
241
+ // ../../src/cli-sdk/src/shell-setup/posix.ts
242
+ import { existsSync } from "node:fs";
243
+ import { lstat, readFile as readFile2, realpath, stat } from "node:fs/promises";
244
+ import { homedir } from "node:os";
245
+ import { dirname, isAbsolute, resolve as resolve2 } from "node:path";
246
+ var blockStart = "# vlt";
247
+ var blockEnd = "# vlt end";
248
+ var abs = (v) => v && isAbsolute(v) ? v : void 0;
249
+ var isENOENT = (er) => er.code === "ENOENT";
250
+ var ownerOf = (st) => ({ uid: st.uid, gid: st.gid });
251
+ var dirOwner = async (dir) => {
252
+ let st = await stat(dir).catch(() => void 0);
253
+ while (!st && dirname(dir) !== dir) {
254
+ dir = dirname(dir);
255
+ st = await stat(dir).catch(() => void 0);
256
+ }
257
+ return st && ownerOf(st);
258
+ };
259
+ var latin1 = (s) => Buffer.from(s).toString("latin1");
260
+ var bytes = (s) => Buffer.from(s, "latin1");
261
+ var rcFiles = (shell, {
262
+ env = process.env,
263
+ platform = process.platform,
264
+ home = homedir()
265
+ } = {}) => {
266
+ const h = (f) => resolve2(home, f);
267
+ switch (shell) {
268
+ case "zsh":
269
+ return [resolve2(abs(env.ZDOTDIR) ?? home, ".zshrc")];
270
+ case "fish":
271
+ return [
272
+ resolve2(
273
+ abs(env.XDG_CONFIG_HOME) ?? h(".config"),
274
+ "fish/conf.d/vlt.fish"
275
+ )
276
+ ];
277
+ case "sh":
278
+ return [resolve2(abs(env.ENV) ?? h(".profile"))];
279
+ case "bash": {
280
+ const login = [".bash_profile", ".bash_login"].map(h);
281
+ const list = [...login, h(".bashrc")].filter((f) => existsSync(f));
282
+ if (!list.length || platform === "darwin" && !login.some((f) => list.includes(f))) {
283
+ list.push(h(".profile"));
284
+ }
285
+ return list;
286
+ }
287
+ }
288
+ };
289
+ var renderBlock = (shell, globalDir, o = {}) => {
290
+ let line;
291
+ if (shell === "fish") {
292
+ const f = fishPath(envFishFile(globalDir), o);
293
+ line = `test -f ${f}; and source ${f}`;
294
+ } else {
295
+ const f = posixPath(envFile(globalDir), o);
296
+ line = `if [ -f ${f} ]; then . ${f}; fi`;
297
+ }
298
+ return `${blockStart}
299
+ ${line}
300
+ ${blockEnd}`;
301
+ };
302
+ var trimEnd = (line) => line.replace(/[\r \t]+$/, "");
303
+ var findBlock = (content) => {
304
+ let start;
305
+ let found;
306
+ let offset = 0;
307
+ for (const raw of content.split("\n")) {
308
+ const line = trimEnd(raw);
309
+ if (line === blockStart) start = offset;
310
+ else if (line === blockEnd && start !== void 0) {
311
+ found = { start, end: offset + line.length };
312
+ start = void 0;
313
+ }
314
+ offset += raw.length + 1;
315
+ }
316
+ if (!found) return;
317
+ const text = content.slice(found.start, found.end).split("\n").map(trimEnd).join("\n");
318
+ return { ...found, text };
319
+ };
320
+ var planEnvFile = async (file, text) => {
321
+ const content = Buffer.from(text);
322
+ const previous = await readFile2(file).catch((er) => {
323
+ if (isENOENT(er)) return void 0;
324
+ throw er;
325
+ });
326
+ return {
327
+ file,
328
+ kind: "env",
329
+ content,
330
+ action: previous === void 0 ? "create" : previous.equals(content) ? "unchanged" : "replace"
331
+ };
332
+ };
333
+ var planRcFile = async (file, block) => {
334
+ const lst = await lstat(file).catch((er) => {
335
+ if (isENOENT(er)) return void 0;
336
+ throw er;
337
+ });
338
+ if (!lst) {
339
+ return {
340
+ file,
341
+ kind: "rc",
342
+ action: "create",
343
+ content: Buffer.from(block + "\n"),
344
+ owner: await dirOwner(dirname(file))
345
+ };
346
+ }
347
+ if (lst.isSymbolicLink()) {
348
+ file = await realpath(file);
349
+ }
350
+ const st = await stat(file);
351
+ const previous = await readFile2(file);
352
+ const text = previous.toString("latin1");
353
+ const blk = latin1(block);
354
+ const base = {
355
+ file,
356
+ kind: "rc",
357
+ mode: st.mode & 4095,
358
+ owner: ownerOf(st)
359
+ };
360
+ const b = findBlock(text);
361
+ if (!b) {
362
+ const sep2 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
363
+ return {
364
+ ...base,
365
+ action: "append",
366
+ content: bytes(text + sep2 + blk + "\n"),
367
+ previous
368
+ };
369
+ }
370
+ if (b.text === blk) {
371
+ return { ...base, action: "unchanged", content: previous };
372
+ }
373
+ return {
374
+ ...base,
375
+ action: "replace",
376
+ content: bytes(text.slice(0, b.start) + blk + text.slice(b.end)),
377
+ previous
378
+ };
379
+ };
380
+
381
+ // ../../src/cli-sdk/src/shell-setup/index.ts
382
+ var posixShells = /* @__PURE__ */ new Set([
383
+ "bash",
384
+ "zsh",
385
+ "fish",
386
+ "sh"
387
+ ]);
388
+ var canSetupPath = (shell, platform = process.platform) => (
389
+ // win32: the user Path reaches every shell
390
+ platform === "win32" || posixShells.has(shell)
391
+ );
392
+ var planPathSetup = async (o) => {
393
+ const { globalDir, dir, shell } = o;
394
+ if ((o.platform ?? process.platform) === "win32") {
395
+ const { env } = o;
396
+ const registry = await planWindowsPath(dir, { env });
397
+ return { globalDir, dir, shell, changes: [], registry, env };
398
+ }
399
+ const command = shellPathCommand(shell, dir, o);
400
+ if (!canSetupPath(shell, o.platform)) {
401
+ const what = shell === "unknown" ? "your shell" : shell;
402
+ throw error(
403
+ `vlt setup --path doesn't support ${what} yet. Add it to your PATH yourself:
404
+ ${command}`,
405
+ { code: "ECONFIG", found: shell }
406
+ );
407
+ }
408
+ const changes = [
409
+ await planEnvFile(envFile(globalDir), renderEnv(dir, o)),
410
+ await planEnvFile(envFishFile(globalDir), renderEnvFish(dir, o))
411
+ ];
412
+ const posix = shell;
413
+ const block = renderBlock(posix, globalDir, o);
414
+ const seen = /* @__PURE__ */ new Set();
415
+ for (const f of rcFiles(posix, o)) {
416
+ const c = await planRcFile(f, block);
417
+ const real2 = await realpath2(c.file).catch(() => c.file);
418
+ if (seen.has(real2)) continue;
419
+ seen.add(real2);
420
+ changes.push(c);
421
+ }
422
+ return { globalDir, dir, shell, changes };
423
+ };
424
+ var pathSetupChanged = (plan) => plan.changes.some((c) => c.action !== "unchanged") || !!plan.registry && plan.registry.action !== "unchanged";
425
+ var pathSetupFiles = (plan) => {
426
+ const files = plan.changes.map(
427
+ ({ file, kind, action }) => ({ file, kind, action })
428
+ );
429
+ const reg = plan.registry;
430
+ if (reg) {
431
+ files.push({
432
+ file: reg.key,
433
+ kind: "registry",
434
+ action: reg.action
435
+ });
436
+ }
437
+ return files;
438
+ };
439
+ var rcList = (files, home) => files.filter((f) => f.kind !== "env").map(
440
+ (f) => f.kind === "registry" ? userEnvLabel : prettyPath(f.file, home)
441
+ ).join(", ");
442
+ var applyPathSetup = async (plan) => {
443
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
444
+ const backupDir = resolve3(plan.globalDir, "backups");
445
+ const backups = [];
446
+ const backup = async (name, data, mode) => {
447
+ await mkdir(backupDir, { recursive: true });
448
+ const b = resolve3(backupDir, `${name}.${stamp}.bak`);
449
+ await writeFile(b, data, { mode });
450
+ backups.push(b);
451
+ };
452
+ for (const c of plan.changes) {
453
+ if (c.action === "unchanged") continue;
454
+ if (c.previous !== void 0) {
455
+ await backup(
456
+ basename(c.file).replace(/^\./, ""),
457
+ c.previous,
458
+ c.mode
459
+ );
460
+ }
461
+ const owner = process.getuid?.() === 0 ? c.owner : void 0;
462
+ const own = [c.file];
463
+ let d = dirname2(c.file);
464
+ while (owner && !existsSync2(d)) {
465
+ own.push(d);
466
+ d = dirname2(d);
467
+ }
468
+ await mkdir(dirname2(c.file), { recursive: true });
469
+ await writeFileAtomic(c.file, c.content, c.mode);
470
+ if (owner) {
471
+ for (const f of own) await chown(f, owner.uid, owner.gid);
472
+ }
473
+ }
474
+ const reg = plan.registry;
475
+ if (reg && reg.action !== "unchanged") {
476
+ if (reg.previous !== void 0) await backup("Path", reg.previous);
477
+ await applyWindowsPath(reg, { env: plan.env });
478
+ }
479
+ return {
480
+ dir: plan.dir,
481
+ shell: plan.shell,
482
+ files: pathSetupFiles(plan),
483
+ backups
484
+ };
485
+ };
486
+ var sourceCommand = (shell, globalDir, dir, o = {}) => (
487
+ // no env file on win32
488
+ (o.platform ?? process.platform) === "win32" ? shellPathCommand(shell, dir, o) : shell === "fish" ? `source ${fishPath(envFishFile(globalDir), o)}` : shell === "sh" ? `. ${posixPath(envFile(globalDir), o)}` : `source ${posixPath(envFile(globalDir), o)}`
489
+ );
490
+ var pathSetupLines = (r, source, home) => {
491
+ const lines = [
492
+ `\u2705 Added ${prettyPath(r.dir, home)} to your PATH in ${rcList(r.files, home)}`,
493
+ ` Open a new terminal${r.files.some((f) => f.kind === "registry") ? " (restart editors like VS Code)" : ""}, or run: ${source}`
494
+ ];
495
+ const [b] = r.backups;
496
+ if (b) lines.push(` Backups in ${prettyPath(dirname2(b), home)}`);
497
+ return lines;
498
+ };
499
+ var ask = async (question, {
500
+ input = process.stdin,
501
+ output = process.stdout
502
+ } = {}) => {
503
+ const rl = createInterface({ input, output });
504
+ try {
505
+ return (await rl.question(question)).trim();
506
+ } finally {
507
+ rl.close();
508
+ input.pause();
509
+ }
510
+ };
511
+ var offerPathSetup = async (g, o) => {
512
+ const {
513
+ globalDir,
514
+ input = process.stdin,
515
+ output = process.stdout,
516
+ env = process.env,
517
+ platform,
518
+ home
519
+ } = o;
520
+ if (o.noModifyPath || g.inPath) return;
521
+ if (!g.bins.length && !g.conflicts.length) return;
522
+ if (!input.isTTY || !output.isTTY || env.CI) return;
523
+ if ((await readGlobalState(globalDir)).pathSetup === "declined")
524
+ return;
525
+ const sh = { env, platform, home };
526
+ const shell = detectShell(env, platform);
527
+ const po = { ...sh, globalDir, dir: g.binDir, shell };
528
+ let plan;
529
+ try {
530
+ plan = await planPathSetup(po);
531
+ } catch {
532
+ return;
533
+ }
534
+ const rcs = rcList(pathSetupFiles(plan), home);
535
+ const source = sourceCommand(shell, globalDir, g.binDir, sh);
536
+ const write = (line) => output.write(line + "\n");
537
+ o.beforeOutput?.();
538
+ write("");
539
+ if (!pathSetupChanged(plan)) {
540
+ write(
541
+ `\u2139\uFE0F It's already added in ${rcs}: open a new terminal, or run: ${source}`
542
+ );
543
+ return;
544
+ }
545
+ if (!o.yes) {
546
+ let answer;
547
+ try {
548
+ answer = await ask(`Add it to ${rcs} now? (Y/n) `, {
549
+ input,
550
+ output
551
+ });
552
+ } catch {
553
+ return;
554
+ }
555
+ if (/^n/i.test(answer)) {
556
+ await updateGlobalState(globalDir, (s) => ({
557
+ ...s,
558
+ pathSetup: "declined"
559
+ })).catch(() => {
560
+ });
561
+ return;
562
+ }
563
+ }
564
+ try {
565
+ if (!o.yes) plan = await planPathSetup(po);
566
+ const r = await applyPathSetup(plan);
567
+ for (const line of pathSetupLines(r, source, home)) write(line);
568
+ } catch (er) {
569
+ write(`\u26A0\uFE0F Could not add it to your PATH: ${asError(er).message}`);
570
+ }
571
+ };
572
+
573
+ // ../../src/cli-sdk/src/global.ts
574
+ import { existsSync as existsSync3, readdirSync, realpathSync } from "node:fs";
575
+ import {
576
+ lstat as lstat2,
577
+ mkdir as mkdir2,
578
+ readdir,
579
+ realpath as realpath3,
580
+ rm as rm2,
581
+ stat as stat2,
582
+ symlink,
583
+ writeFile as writeFile2
584
+ } from "node:fs/promises";
585
+ import { homedir as homedir2 } from "node:os";
586
+ import {
587
+ basename as basename2,
588
+ delimiter,
589
+ isAbsolute as isAbsolute2,
590
+ relative,
591
+ resolve as resolve4,
592
+ sep
593
+ } from "node:path";
594
+ var unsupported = [
595
+ "workspace",
596
+ "workspace-group",
597
+ "lockfile-only"
598
+ ];
599
+ var assertGlobalOptions = (conf) => {
600
+ for (const name of unsupported) {
601
+ const found = conf.values[name];
602
+ if (found !== void 0 && found !== false) {
603
+ throw error(`--${name} is not supported with --global`, {
604
+ code: "EUSAGE",
605
+ name,
606
+ found
607
+ });
608
+ }
609
+ }
610
+ };
611
+ var workspaceId = (path) => joinDepIDTuple(["workspace", path]);
612
+ var specs = /* @__PURE__ */ new WeakMap();
613
+ var globalSpec = (item, conf) => {
614
+ const known = specs.get(conf) ?? /* @__PURE__ */ new Map();
615
+ specs.set(conf, known);
616
+ const spec = known.get(item) ?? namedSpec(item, conf);
617
+ known.set(item, spec);
618
+ return spec;
619
+ };
620
+ var namedSpec = async (item, conf) => {
621
+ const options = conf.options;
622
+ let spec = parseSpecArg(item, options);
623
+ if (spec.type === "file" && spec.file && !isAbsolute2(spec.file)) {
624
+ const file = resolve4(process.cwd(), spec.file).split(sep).join("/");
625
+ spec = Spec.parse(spec.name, `file:${file}`, options);
626
+ }
627
+ if (spec.type === "registry" && !spec.bareSpec) {
628
+ return Spec.parse(spec.name, options.tag, options);
629
+ }
630
+ if (spec.name !== "(unknown)") return spec;
631
+ const { name } = await options.packageInfo.manifest(spec, {
632
+ from: process.cwd()
633
+ });
634
+ if (!name) {
635
+ throw error("Could not determine package name", {
636
+ code: "EUSAGE",
637
+ spec
638
+ });
639
+ }
640
+ return Spec.parse(name, spec.bareSpec, options);
641
+ };
642
+ var wsPackageName = (dir) => dir.replace(/-ws$/, "").replace("+", "/");
643
+ var findWorkspace = (projectRoot, name) => {
644
+ const path = globalWorkspacePath(name);
645
+ const dir = resolve4(projectRoot, path);
646
+ const base = basename2(path);
647
+ const entries = readdirSync(
648
+ resolve4(projectRoot, globalWorkspacesDir)
649
+ );
650
+ const variant = entries.find(
651
+ (e) => e !== base && e.toLowerCase() === base.toLowerCase()
652
+ );
653
+ return {
654
+ path,
655
+ dir,
656
+ exists: entries.includes(base) && existsSync3(resolve4(dir, "package.json")),
657
+ variant: variant && wsPackageName(variant)
658
+ };
659
+ };
660
+ var parseGlobalAddArgs = async (conf) => {
661
+ const { positionals, projectRoot } = conf;
662
+ const add = Object.assign(
663
+ /* @__PURE__ */ new Map(),
664
+ { modifiedDependencies: positionals.length > 0 }
665
+ );
666
+ const created = [];
667
+ const importers = /* @__PURE__ */ new Set();
668
+ try {
669
+ for (const item of positionals) {
670
+ const spec = await globalSpec(item, conf);
671
+ const { path, dir, exists: exists2, variant } = findWorkspace(
672
+ projectRoot,
673
+ spec.name
674
+ );
675
+ if (!exists2) {
676
+ if (variant) {
677
+ throw error(
678
+ `${spec.name} differs only in case from global package ${variant}`,
679
+ { code: "EUSAGE", found: spec.name }
680
+ );
681
+ }
682
+ await mkdir2(dir, { recursive: true });
683
+ created.push(dir);
684
+ const ws = {
685
+ name: globalWorkspaceName(spec.name),
686
+ private: true
687
+ };
688
+ await writeFile2(
689
+ resolve4(dir, "package.json"),
690
+ JSON.stringify(ws, null, 2) + "\n"
691
+ );
692
+ }
693
+ const id = workspaceId(path);
694
+ importers.add(id);
695
+ const dep = { spec, type: "implicit" };
696
+ add.set(id, /* @__PURE__ */ new Map([[spec.name, dep]]));
697
+ }
698
+ } catch (er) {
699
+ await removeGlobalWorkspaces(created);
700
+ throw er;
701
+ }
702
+ if (created.length) conf.resetOptions(projectRoot);
703
+ return {
704
+ add,
705
+ created,
706
+ importers: positionals.length ? importers : void 0
707
+ };
708
+ };
709
+ var parseGlobalRemoveArgs = (conf) => {
710
+ const { positionals, projectRoot } = conf;
711
+ if (!positionals.length) {
712
+ throw error("Missing package name(s) to uninstall", {
713
+ code: "EUSAGE"
714
+ });
715
+ }
716
+ const remove = Object.assign(
717
+ /* @__PURE__ */ new Map(),
718
+ { modifiedDependencies: true }
719
+ );
720
+ const dirs = [];
721
+ for (const name of positionals) {
722
+ const { path, dir, exists: exists2, variant } = findWorkspace(
723
+ projectRoot,
724
+ name
725
+ );
726
+ const id = workspaceId(path);
727
+ if (remove.has(id)) continue;
728
+ if (!exists2) {
729
+ throw error(`${name} is not installed globally`, {
730
+ code: "EUSAGE",
731
+ found: name,
732
+ ...variant ? { validOptions: [variant] } : null
733
+ });
734
+ }
735
+ remove.set(id, /* @__PURE__ */ new Set([name]));
736
+ dirs.push(dir);
737
+ }
738
+ return { remove, dirs };
739
+ };
740
+ var removeGlobalWorkspaces = async (dirs) => {
741
+ await Promise.all(
742
+ dirs.map((dir) => rm2(dir, { recursive: true, force: true }))
743
+ );
744
+ };
745
+ var shimExts = ["", ".cmd", ".ps1", ".pwsh"];
746
+ var linkFiles = (link) => process.platform === "win32" ? shimExts.map((ext) => link + ext) : [link];
747
+ var realOr = (p) => realpath3(p).catch(() => p);
748
+ var unlinkGlobalBins = async (binDir, dirs, remover) => {
749
+ const entries = await readdir(binDir, {
750
+ withFileTypes: true
751
+ }).catch(() => []);
752
+ const names = /* @__PURE__ */ new Set();
753
+ for (const e of entries) {
754
+ const name = e.name.replace(/\.(cmd|ps1|pwsh)$/i, "");
755
+ if (name !== e.name || e.isSymbolicLink()) names.add(name);
756
+ }
757
+ const roots = [...dirs, ...await Promise.all(dirs.map(realOr))];
758
+ const removed = [];
759
+ for (const name of names) {
760
+ const link = resolve4(binDir, name);
761
+ const found = await findCmdShimIfExists(link);
762
+ if (!found || !roots.some((dir) => isInside(dir, found[1])))
763
+ continue;
764
+ await Promise.all(
765
+ linkFiles(link).map(
766
+ (f) => remover ? remover.rm(f) : rm2(f, { force: true })
767
+ )
768
+ );
769
+ removed.push(name);
770
+ }
771
+ return removed.sort((a, b) => a.localeCompare(b, "en"));
772
+ };
773
+ var exists = async (link) => (await Promise.all(
774
+ linkFiles(link).map(
775
+ (f) => lstat2(f).then(
776
+ () => true,
777
+ () => false
778
+ )
779
+ )
780
+ )).some(Boolean);
781
+ var safeBin = (bin) => !!bin && bin === basename2(bin) && !bin.includes("\\") && bin !== "." && bin !== "..";
782
+ var sorted = (s) => [...s].sort((a, b) => a.localeCompare(b, "en"));
783
+ var dedupe = (dirs) => dirs.filter((d, i) => dirs.findIndex((x) => samePath(x, d)) === i);
784
+ var otherBinDirs = async (root, current, state) => {
785
+ const g = await realpath3(globalBinDir(root)).catch(() => void 0);
786
+ return dedupe([...state.binDirs ?? [], ...g ? [g] : []]).filter(
787
+ (d) => !samePath(d, current)
788
+ );
789
+ };
790
+ var isDir = (d) => stat2(d).then(
791
+ (s) => s.isDirectory(),
792
+ () => false
793
+ );
794
+ var isPermError = (er) => er instanceof Error && /^(EACCES|EPERM)$/.test(String(er.code));
795
+ var replaceable = async (link, keep) => {
796
+ if (process.platform !== "win32" && !(await lstat2(link)).isSymbolicLink()) {
797
+ return false;
798
+ }
799
+ const found = await findCmdShimIfExists(link);
800
+ if (!found) return false;
801
+ const to = await realOr(found[1]);
802
+ return !keep.some((k) => samePath(k, to));
803
+ };
804
+ var linkBins = async (graph, opts, importers) => {
805
+ const { projectRoot, scurry, force } = opts;
806
+ const { dir: binDir, source } = opts.binDir;
807
+ const state = await readGlobalState(projectRoot);
808
+ const targets = [...graph.importers].filter(
809
+ (i) => i !== graph.mainImporter && (!importers || importers.has(i.id))
810
+ ).sort((a, b) => a.location.localeCompare(b.location, "en"));
811
+ const owned = importers ? targets.map((i) => i.resolvedLocation(scurry)) : [resolve4(projectRoot, globalWorkspacesDir)];
812
+ const keep = force && source !== "global-dir" ? await Promise.all(
813
+ [process.execPath, ...process.argv.slice(1, 2)].map(realOr)
814
+ ) : void 0;
815
+ const remover = new RollbackRemove();
816
+ const bins = /* @__PURE__ */ new Set();
817
+ const conflicts = /* @__PURE__ */ new Set();
818
+ const otherDirs = [];
819
+ const created = [];
820
+ try {
821
+ await unlinkGlobalBins(binDir, owned, remover);
822
+ for (const d of await otherBinDirs(projectRoot, binDir, state)) {
823
+ const removed = await unlinkGlobalBins(d, owned, remover).catch(
824
+ () => []
825
+ );
826
+ if (removed.length) otherDirs.push(d);
827
+ }
828
+ await mkdir2(binDir, { recursive: true });
829
+ for (const importer of targets) {
830
+ const nm = await realOr(importer.nodeModules(scurry));
831
+ for (const edge of importer.edgesOut.values()) {
832
+ for (const [bin, path] of Object.entries(
833
+ edge.to?.bins ?? {}
834
+ )) {
835
+ if (!safeBin(bin)) continue;
836
+ const target = resolve4(nm, edge.spec.name, path);
837
+ const win322 = process.platform === "win32";
838
+ if (win322 && !await stat2(target).catch(() => false)) {
839
+ continue;
840
+ }
841
+ const link = resolve4(binDir, bin);
842
+ if (await exists(link) && (!force || keep && !await replaceable(link, keep))) {
843
+ conflicts.add(bin);
844
+ continue;
845
+ }
846
+ if (win322) {
847
+ created.push(link);
848
+ await cmdShimIfExists(target, link, remover);
849
+ } else {
850
+ await remover.rm(link);
851
+ await rm2(link, { force: true });
852
+ created.push(link);
853
+ await symlink(relative(binDir, target), link);
854
+ }
855
+ bins.add(bin);
856
+ }
857
+ }
858
+ }
859
+ } catch (er) {
860
+ await Promise.all(
861
+ created.flatMap(linkFiles).map((f) => rm2(f, { force: true }))
862
+ );
863
+ await remover.rollback();
864
+ throw er;
865
+ }
866
+ remover.confirm();
867
+ return {
868
+ binDir: opts.binDir,
869
+ state,
870
+ bins: sorted(bins),
871
+ conflicts: sorted(conflicts),
872
+ otherDirs
873
+ };
874
+ };
875
+ var recordBinDir = async (projectRoot, { binDir, state, bins, conflicts, otherDirs }) => {
876
+ const { dir, source, inPath, notWritable } = binDir;
877
+ const shown = (bins.length > 0 || conflicts.length > 0) && (source === "global-dir" || !state.localBinNoticed);
878
+ const why = shown ? notWritable : void 0;
879
+ const notice = !!why && source === "local-bin";
880
+ const recorded = [];
881
+ for (const d of state.binDirs ?? []) {
882
+ if (await isDir(d)) recorded.push(d);
883
+ }
884
+ await updateGlobalState(projectRoot, (s) => ({
885
+ ...s,
886
+ binDirs: dedupe([...recorded, dir]),
887
+ ...notice ? { localBinNoticed: true } : {}
888
+ }));
889
+ return {
890
+ binDir: dir,
891
+ source,
892
+ bins,
893
+ conflicts,
894
+ inPath,
895
+ otherDirs,
896
+ ...why ? { notWritable: why } : {}
897
+ };
898
+ };
899
+ var linkGlobalBins = async (graph, opts, importers) => {
900
+ let linked;
901
+ try {
902
+ linked = await linkBins(graph, opts, importers);
903
+ } catch (er) {
904
+ const { binDir, fallback } = opts;
905
+ if (binDir.source !== "self" || !fallback || !isPermError(er)) {
906
+ throw er;
907
+ }
908
+ linked = await linkBins(
909
+ graph,
910
+ { ...opts, binDir: await fallback() },
911
+ importers
912
+ );
913
+ }
914
+ return recordBinDir(opts.projectRoot, linked);
915
+ };
916
+ var removeGlobalPackages = async (projectRoot, dirs, binDir) => {
917
+ const current = binDir ?? globalBinDir(projectRoot);
918
+ await unlinkGlobalBins(current, dirs);
919
+ const state = await readGlobalState(projectRoot);
920
+ for (const d of await otherBinDirs(projectRoot, current, state)) {
921
+ await unlinkGlobalBins(d, dirs).catch(() => []);
922
+ }
923
+ await removeGlobalWorkspaces(dirs);
924
+ };
925
+ var isInPath = (dir, PATH = process.env.PATH ?? "") => PATH.split(delimiter).some((p) => !!p && samePath(p, dir));
926
+ var homeOf = (dir, home, win322) => {
927
+ if (prettyPath(dir, home, win322) !== dir) return home;
928
+ try {
929
+ return realpathSync.native(home);
930
+ } catch {
931
+ return home;
932
+ }
933
+ };
934
+ var globalBinsLines = (g, opts = {}) => {
935
+ const {
936
+ shell = detectShell(opts.env, opts.platform),
937
+ platform = process.platform
938
+ } = opts;
939
+ const win322 = platform === "win32";
940
+ const home = homeOf(g.binDir, opts.home ?? homedir2(), win322);
941
+ const pretty = (p) => prettyPath(p, home, win322);
942
+ const dir = pretty(g.binDir);
943
+ const lines = [];
944
+ if (g.notWritable) {
945
+ lines.push(
946
+ `\u2139\uFE0F Using ${dir} because ${pretty(g.notWritable)} is not writable.`
947
+ );
948
+ }
949
+ if (g.bins.length) {
950
+ lines.push(`\u{1F517} Linked ${g.bins.join(", ")} in ${dir}`);
951
+ }
952
+ if (g.conflicts.length) {
953
+ lines.push(
954
+ `\u26A0\uFE0F Skipped ${g.conflicts.join(", ")}: already in ${dir} (use --force to overwrite)`
955
+ );
956
+ }
957
+ if (!g.inPath && (g.bins.length || g.conflicts.length)) {
958
+ const rc = shellRcFile(shell, opts);
959
+ const what = g.bins.length ? g.bins.join(", ") : "global bins";
960
+ const fix = canSetupPath(shell, platform) ? "Run `vlt setup --path` to add it" : "Set --global-bin-dir to a folder on your PATH";
961
+ lines.push(
962
+ // a paragraph of its own: the install offer follows it
963
+ "",
964
+ `\u26A0\uFE0F ${dir} is not on your PATH, so ${what} can't be run yet.`,
965
+ ` ${fix}, or ${rc ? `add this line to ${rc}` : "run"}:`,
966
+ ` ${shellPathCommand(shell, g.binDir, { ...opts, home })}`
967
+ );
968
+ }
969
+ return lines;
970
+ };
971
+
972
+ // ../../src/cli-sdk/src/global-bin-dir.ts
973
+ import { constants } from "node:fs";
974
+ import { access, mkdir as mkdir3, realpath as realpath5, stat as stat3 } from "node:fs/promises";
975
+ import { homedir as homedir3 } from "node:os";
976
+ import {
977
+ basename as basename3,
978
+ delimiter as delimiter2,
979
+ dirname as dirname4,
980
+ isAbsolute as isAbsolute4,
981
+ resolve as resolve6
982
+ } from "node:path";
983
+
984
+ // ../../src/cli-sdk/src/install-receipt.ts
985
+ import { readFile as readFile3, realpath as realpath4 } from "node:fs/promises";
986
+ import { dirname as dirname3, isAbsolute as isAbsolute3, resolve as resolve5 } from "node:path";
987
+ var xdg = new XDG("vlt");
988
+ var receiptName = "install-receipt.json";
989
+ var isStr = (v) => typeof v === "string";
990
+ var optStr = (v) => v === void 0 || isStr(v);
991
+ var optStrs = (v) => v === void 0 || Array.isArray(v) && v.every(isStr);
992
+ var isReceipt = (d) => isObject(d) && d.receiptVersion === 1 && isStr(d.method) && !!d.method && isStr(d.binDir) && isAbsolute3(d.binDir) && (d.installer === void 0 || isObject(d.installer) && optStr(d.installer.name) && optStr(d.installer.version)) && optStr(d.version) && optStr(d.channel) && optStr(d.target) && optStrs(d.binaries) && optStrs(d.modifiedPath) && optStr(d.installedAt);
993
+ var readInstallReceipt = async (found, configDir = xdg.config()) => {
994
+ const dir = dirname3(found);
995
+ const real2 = await realpath4(dir).catch(() => void 0);
996
+ if (!real2) return;
997
+ for (const file of [
998
+ resolve5(configDir, receiptName),
999
+ resolve5(dir, receiptName),
1000
+ resolve5(dir, "..", receiptName)
1001
+ ]) {
1002
+ try {
1003
+ const data = JSON.parse(await readFile3(file, "utf8"));
1004
+ if (isReceipt(data) && samePath(await realpath4(data.binDir), real2))
1005
+ return { file, data };
1006
+ } catch {
1007
+ }
1008
+ }
1009
+ };
1010
+ var writeInstallReceipt = async (file, update) => {
1011
+ let raw;
1012
+ try {
1013
+ raw = JSON.parse(await readFile3(file, "utf8"));
1014
+ } catch (cause) {
1015
+ throw error("Invalid install receipt", { path: file, cause });
1016
+ }
1017
+ if (!isReceipt(raw)) {
1018
+ throw error("Invalid install receipt", { path: file });
1019
+ }
1020
+ await writeJsonAtomic(file, {
1021
+ ...raw,
1022
+ version: update.version,
1023
+ installedAt: update.installedAt ?? (/* @__PURE__ */ new Date()).toISOString()
1024
+ });
1025
+ };
1026
+
1027
+ // ../../src/cli-sdk/src/global-bin-dir.ts
1028
+ var real = (p) => realpath5(p).catch(() => void 0);
1029
+ var writable = (dir) => access(dir, constants.W_OK).then(
1030
+ () => true,
1031
+ () => false
1032
+ );
1033
+ var isInPathRealpath = async (dir, PATH = process.env.PATH ?? "") => {
1034
+ if (isInPath(dir, PATH)) return true;
1035
+ const r = await real(dir);
1036
+ if (!r) return false;
1037
+ for (const p of PATH.split(delimiter2)) {
1038
+ const rp = p && await real(p);
1039
+ if (rp && samePath(rp, r)) return true;
1040
+ }
1041
+ return false;
1042
+ };
1043
+ var isDotBin = (d) => {
1044
+ const name = (p) => process.platform === "win32" ? basename3(p).toLowerCase() : basename3(p);
1045
+ return name(d) === ".bin" && name(dirname4(d)) === "node_modules";
1046
+ };
1047
+ var findSelf = async () => {
1048
+ const found = await which("vlt", { nothrow: true }).catch(
1049
+ () => null
1050
+ );
1051
+ if (!found || !isAbsolute4(found)) return;
1052
+ const foundDir = dirname4(found);
1053
+ if (!isInPath(foundDir) || isDotBin(foundDir)) return;
1054
+ const dir = await real(foundDir);
1055
+ if (!dir || isDotBin(dir)) return;
1056
+ const shim = /\.(cmd|ps1)$/i.test(found) ? (await findCmdShimIfExists(found))?.[1] : found;
1057
+ const target = shim && await real(shim);
1058
+ if (!target) return;
1059
+ const exec = await real(process.execPath);
1060
+ const standalone = !!exec && samePath(target, exec);
1061
+ if (!standalone) {
1062
+ const script = process.argv[1] && await real(process.argv[1]);
1063
+ if (!script || !samePath(target, script)) return;
1064
+ }
1065
+ const receipt = await readInstallReceipt(found);
1066
+ return {
1067
+ found,
1068
+ dir,
1069
+ target,
1070
+ standalone,
1071
+ ...receipt ? { receipt } : {}
1072
+ };
1073
+ };
1074
+ var resolveDir = async (conf, selfUnwritable) => {
1075
+ const configured = conf.globalBinDir;
1076
+ if (configured) {
1077
+ try {
1078
+ await mkdir3(configured, { recursive: true });
1079
+ } catch (cause) {
1080
+ throw error("Could not create global-bin-dir", {
1081
+ code: "ECONFIG",
1082
+ found: configured,
1083
+ cause
1084
+ });
1085
+ }
1086
+ try {
1087
+ await access(configured, constants.W_OK);
1088
+ } catch (cause) {
1089
+ throw error("global-bin-dir is not writable", {
1090
+ code: "ECONFIG",
1091
+ found: configured,
1092
+ cause
1093
+ });
1094
+ }
1095
+ const dir2 = await realpath5(configured);
1096
+ return {
1097
+ dir: dir2,
1098
+ source: "config",
1099
+ inPath: await isInPathRealpath(dir2)
1100
+ };
1101
+ }
1102
+ const self = await findSelf();
1103
+ if (self && !selfUnwritable && await writable(self.dir)) {
1104
+ return { dir: self.dir, source: "self", inPath: true };
1105
+ }
1106
+ const notWritable = self?.dir;
1107
+ if (notWritable && process.platform !== "win32") {
1108
+ const local = resolve6(homedir3(), ".local/bin");
1109
+ const st = await stat3(local).catch(() => void 0);
1110
+ if (st?.isDirectory() && await isInPathRealpath(local) && await writable(local)) {
1111
+ const dir2 = await realpath5(local);
1112
+ if (!samePath(dir2, notWritable)) {
1113
+ return { dir: dir2, source: "local-bin", inPath: true, notWritable };
1114
+ }
1115
+ }
1116
+ }
1117
+ const g = globalBinDir(conf.projectRoot);
1118
+ await mkdir3(g, { recursive: true });
1119
+ const dir = await realpath5(g);
1120
+ return {
1121
+ dir,
1122
+ source: "global-dir",
1123
+ inPath: await isInPathRealpath(dir),
1124
+ ...notWritable ? { notWritable } : {}
1125
+ };
1126
+ };
1127
+ var resolveGlobalBinDir = async (conf, { selfUnwritable = false } = {}) => {
1128
+ const r = await resolveDir(conf, selfUnwritable);
1129
+ process.env.VLT_GLOBAL_BIN_DIR = r.dir;
1130
+ return r;
1131
+ };
1132
+
1133
+ export {
1134
+ editPathHint,
1135
+ planPathSetup,
1136
+ pathSetupChanged,
1137
+ pathSetupFiles,
1138
+ rcList,
1139
+ applyPathSetup,
1140
+ sourceCommand,
1141
+ pathSetupLines,
1142
+ ask,
1143
+ offerPathSetup,
1144
+ assertGlobalOptions,
1145
+ globalSpec,
1146
+ parseGlobalAddArgs,
1147
+ parseGlobalRemoveArgs,
1148
+ removeGlobalWorkspaces,
1149
+ linkGlobalBins,
1150
+ removeGlobalPackages,
1151
+ globalBinsLines,
1152
+ writeInstallReceipt,
1153
+ findSelf,
1154
+ resolveGlobalBinDir
1155
+ };