UNPKG

@visulima/package

Version:

One Package to rule them all, finds your root-dir, monorepo, or package manager.

1,266 lines (1,257 loc) 39.6 kB
import { existsSync } from 'node:fs'; import process$1 from 'node:process'; import fs from 'node:fs/promises'; import path, { resolve as resolve$1 } from 'node:path'; import { createRequire } from 'node:module'; import { spawn } from 'child_process'; import { delimiter, resolve, dirname, normalize } from 'path'; import { cwd } from 'process'; import { PassThrough } from 'stream'; import me from 'readline'; import confirm from '@inquirer/confirm'; import { findUp, readJson, findUpSync, readJsonSync, writeJson, writeJsonSync } from '@visulima/fs'; import { NotFoundError } from '@visulima/fs/error'; import { toPath, parseJson } from '@visulima/fs/utils'; import { join } from '@visulima/path'; import normalizeData from 'normalize-package-data'; const AGENTS = [ "npm", "yarn", "yarn@berry", "pnpm", "pnpm@6", "bun", "deno" ]; const LOCKS = { "bun.lock": "bun", "bun.lockb": "bun", "deno.lock": "deno", "pnpm-lock.yaml": "pnpm", "pnpm-workspace.yaml": "pnpm", "yarn.lock": "yarn", "package-lock.json": "npm", "npm-shrinkwrap.json": "npm" }; const INSTALL_METADATA = { "node_modules/.deno/": "deno", "node_modules/.pnpm/": "pnpm", "node_modules/.yarn-state.yml": "yarn", // yarn v2+ (node-modules) "node_modules/.yarn_integrity": "yarn", // yarn v1 "node_modules/.package-lock.json": "npm", ".pnp.cjs": "yarn", // yarn v3+ (pnp) ".pnp.js": "yarn", // yarn v2 (pnp) "bun.lock": "bun", "bun.lockb": "bun" }; var __defProp$4 = Object.defineProperty; var __name$4 = (target, value) => __defProp$4(target, "name", { value, configurable: true }); async function pathExists(path2, type) { try { const stat = await fs.stat(path2); return type === "file" ? stat.isFile() : stat.isDirectory(); } catch { return false; } } __name$4(pathExists, "pathExists"); function getUserAgent() { const userAgent = process$1.env.npm_config_user_agent; if (!userAgent) { return null; } const name = userAgent.split("/")[0]; return AGENTS.includes(name) ? name : null; } __name$4(getUserAgent, "getUserAgent"); function* lookup(cwd = process$1.cwd()) { let directory = path.resolve(cwd); const { root } = path.parse(directory); while (directory && directory !== root) { yield directory; directory = path.dirname(directory); } } __name$4(lookup, "lookup"); async function parsePackageJson$1(filepath, onUnknown) { return !filepath || !pathExists(filepath, "file") ? null : await handlePackageManager(filepath, onUnknown); } __name$4(parsePackageJson$1, "parsePackageJson"); async function detect(options = {}) { const { cwd, strategies = ["lockfile", "packageManager-field", "devEngines-field"], onUnknown } = options; let stopDir; if (typeof options.stopDir === "string") { const resolved = path.resolve(options.stopDir); stopDir = /* @__PURE__ */ __name$4((dir) => dir === resolved, "stopDir"); } else { stopDir = options.stopDir; } for (const directory of lookup(cwd)) { for (const strategy of strategies) { switch (strategy) { case "lockfile": { for (const lock of Object.keys(LOCKS)) { if (await pathExists(path.join(directory, lock), "file")) { const name = LOCKS[lock]; const result = await parsePackageJson$1(path.join(directory, "package.json"), onUnknown); if (result) return result; else return { name, agent: name }; } } break; } case "packageManager-field": case "devEngines-field": { const result = await parsePackageJson$1(path.join(directory, "package.json"), onUnknown); if (result) return result; break; } case "install-metadata": { for (const metadata of Object.keys(INSTALL_METADATA)) { const fileOrDir = metadata.endsWith("/") ? "dir" : "file"; if (await pathExists(path.join(directory, metadata), fileOrDir)) { const name = INSTALL_METADATA[metadata]; const agent = name === "yarn" ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name; return { name, agent }; } } break; } } } if (stopDir?.(directory)) break; } return null; } __name$4(detect, "detect"); function getNameAndVer(pkg) { const handelVer = /* @__PURE__ */ __name$4((version) => version?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version, "handelVer"); if (typeof pkg.packageManager === "string") { const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@"); return { name, ver: handelVer(ver) }; } if (typeof pkg.devEngines?.packageManager?.name === "string") { return { name: pkg.devEngines.packageManager.name, ver: handelVer(pkg.devEngines.packageManager.version) }; } return void 0; } __name$4(getNameAndVer, "getNameAndVer"); async function handlePackageManager(filepath, onUnknown) { try { const pkg = JSON.parse(await fs.readFile(filepath, "utf8")); let agent; const nameAndVer = getNameAndVer(pkg); if (nameAndVer) { const name = nameAndVer.name; const ver = nameAndVer.ver; let version = ver; if (name === "yarn" && ver && Number.parseInt(ver) > 1) { agent = "yarn@berry"; version = "berry"; return { name, agent, version }; } else if (name === "pnpm" && ver && Number.parseInt(ver) < 7) { agent = "pnpm@6"; return { name, agent, version }; } else if (AGENTS.includes(name)) { agent = name; return { name, agent, version }; } else { return onUnknown?.(pkg.packageManager) ?? null; } } } catch { } return null; } __name$4(handlePackageManager, "handlePackageManager"); function isMetadataYarnClassic(metadataPath) { return metadataPath.endsWith(".yarn_integrity"); } __name$4(isMetadataYarnClassic, "isMetadataYarnClassic"); var __defProp$3 = Object.defineProperty; var __name$3 = (target, value) => __defProp$3(target, "name", { value, configurable: true }); const require2 = createRequire(import.meta.url); var St = Object.create; var $ = Object.defineProperty; var kt = Object.getOwnPropertyDescriptor; var Tt = Object.getOwnPropertyNames; var At = Object.getPrototypeOf; var Rt = Object.prototype.hasOwnProperty; var h = /* @__PURE__ */ ((t) => typeof require2 < "u" ? require2 : typeof Proxy < "u" ? new Proxy(t, { get: /* @__PURE__ */ __name$3((e, n) => (typeof require2 < "u" ? require2 : e)[n], "get") }) : t)(function(t) { if (typeof require2 < "u") return require2.apply(this, arguments); throw Error('Dynamic require of "' + t + '" is not supported'); }); var l = /* @__PURE__ */ __name$3((t, e) => () => (e || t((e = { exports: {} }).exports, e), e.exports), "l"); var $t = /* @__PURE__ */ __name$3((t, e, n, r) => { if (e && typeof e == "object" || typeof e == "function") for (let s of Tt(e)) !Rt.call(t, s) && s !== n && $(t, s, { get: /* @__PURE__ */ __name$3(() => e[s], "get"), enumerable: !(r = kt(e, s)) || r.enumerable }); return t; }, "$t"); var Nt = /* @__PURE__ */ __name$3((t, e, n) => (n = t != null ? St(At(t)) : {}, $t( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. e || !t || !t.__esModule ? $(n, "default", { value: t, enumerable: true }) : n, t )), "Nt"); var W = l((Se, H) => { H.exports = z; z.sync = Wt; var j = h("fs"); function Ht(t, e) { var n = e.pathExt !== void 0 ? e.pathExt : process.env.PATHEXT; if (!n || (n = n.split(";"), n.indexOf("") !== -1)) return true; for (var r = 0; r < n.length; r++) { var s = n[r].toLowerCase(); if (s && t.substr(-s.length).toLowerCase() === s) return true; } return false; } __name$3(Ht, "Ht"); function F(t, e, n) { return !t.isSymbolicLink() && !t.isFile() ? false : Ht(e, n); } __name$3(F, "F"); function z(t, e, n) { j.stat(t, function(r, s) { n(r, r ? false : F(s, t, e)); }); } __name$3(z, "z"); function Wt(t, e) { return F(j.statSync(t), t, e); } __name$3(Wt, "Wt"); }); var X = l((ke, B) => { B.exports = K; K.sync = Dt; var D = h("fs"); function K(t, e, n) { D.stat(t, function(r, s) { n(r, r ? false : M(s, e)); }); } __name$3(K, "K"); function Dt(t, e) { return M(D.statSync(t), e); } __name$3(Dt, "Dt"); function M(t, e) { return t.isFile() && Kt(t, e); } __name$3(M, "M"); function Kt(t, e) { var n = t.mode, r = t.uid, s = t.gid, o = e.uid !== void 0 ? e.uid : process.getuid && process.getuid(), i = e.gid !== void 0 ? e.gid : process.getgid && process.getgid(), a = parseInt("100", 8), c = parseInt("010", 8), u = parseInt("001", 8), f = a | c, p = n & u || n & c && s === i || n & a && r === o || n & f && o === 0; return p; } __name$3(Kt, "Kt"); }); var U = l((Ae, G) => { h("fs"); var v; process.platform === "win32" || global.TESTING_WINDOWS ? v = W() : v = X(); G.exports = y; y.sync = Mt; function y(t, e, n) { if (typeof e == "function" && (n = e, e = {}), !n) { if (typeof Promise != "function") throw new TypeError("callback not provided"); return new Promise(function(r, s) { y(t, e || {}, function(o, i) { o ? s(o) : r(i); }); }); } v(t, e || {}, function(r, s) { r && (r.code === "EACCES" || e && e.ignoreErrors) && (r = null, s = false), n(r, s); }); } __name$3(y, "y"); function Mt(t, e) { try { return v.sync(t, e || {}); } catch (n) { if (e && e.ignoreErrors || n.code === "EACCES") return false; throw n; } } __name$3(Mt, "Mt"); }); var et = l((Re, tt) => { var g = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys", Y = h("path"), Bt = g ? ";" : ":", V = U(), J = /* @__PURE__ */ __name$3((t) => Object.assign(new Error(`not found: ${t}`), { code: "ENOENT" }), "J"), Q = /* @__PURE__ */ __name$3((t, e) => { let n = e.colon || Bt, r = t.match(/\//) || g && t.match(/\\/) ? [""] : [ // windows always checks the cwd first ...g ? [process.cwd()] : [], ...(e.path || process.env.PATH || /* istanbul ignore next: very unusual */ "").split(n) ], s = g ? e.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "", o = g ? s.split(n) : [""]; return g && t.indexOf(".") !== -1 && o[0] !== "" && o.unshift(""), { pathEnv: r, pathExt: o, pathExtExe: s }; }, "Q"), Z = /* @__PURE__ */ __name$3((t, e, n) => { typeof e == "function" && (n = e, e = {}), e || (e = {}); let { pathEnv: r, pathExt: s, pathExtExe: o } = Q(t, e), i = [], a = /* @__PURE__ */ __name$3((u) => new Promise((f, p) => { if (u === r.length) return e.all && i.length ? f(i) : p(J(t)); let d = r[u], w = /^".*"$/.test(d) ? d.slice(1, -1) : d, m = Y.join(w, t), b = !w && /^\.[\\\/]/.test(t) ? t.slice(0, 2) + m : m; f(c(b, u, 0)); }), "a"), c = /* @__PURE__ */ __name$3((u, f, p) => new Promise((d, w) => { if (p === s.length) return d(a(f + 1)); let m = s[p]; V(u + m, { pathExt: o }, (b, Ot) => { if (!b && Ot) if (e.all) i.push(u + m); else return d(u + m); return d(c(u, f, p + 1)); }); }), "c"); return n ? a(0).then((u) => n(null, u), n) : a(0); }, "Z"), Xt = /* @__PURE__ */ __name$3((t, e) => { e = e || {}; let { pathEnv: n, pathExt: r, pathExtExe: s } = Q(t, e), o = []; for (let i = 0; i < n.length; i++) { let a = n[i], c = /^".*"$/.test(a) ? a.slice(1, -1) : a, u = Y.join(c, t), f = !c && /^\.[\\\/]/.test(t) ? t.slice(0, 2) + u : u; for (let p = 0; p < r.length; p++) { let d = f + r[p]; try { if (V.sync(d, { pathExt: s })) if (e.all) o.push(d); else return d; } catch { } } } if (e.all && o.length) return o; if (e.nothrow) return null; throw J(t); }, "Xt"); tt.exports = Z; Z.sync = Xt; }); var rt = l(($e, _) => { var nt = /* @__PURE__ */ __name$3((t = {}) => { let e = t.env || process.env; return (t.platform || process.platform) !== "win32" ? "PATH" : Object.keys(e).reverse().find((r) => r.toUpperCase() === "PATH") || "Path"; }, "nt"); _.exports = nt; _.exports.default = nt; }); var ct = l((Ne, it) => { var st = h("path"), Gt = et(), Ut = rt(); function ot(t, e) { let n = t.options.env || process.env, r = process.cwd(), s = t.options.cwd != null, o = s && process.chdir !== void 0 && !process.chdir.disabled; if (o) try { process.chdir(t.options.cwd); } catch { } let i; try { i = Gt.sync(t.command, { path: n[Ut({ env: n })], pathExt: e ? st.delimiter : void 0 }); } catch { } finally { o && process.chdir(r); } return i && (i = st.resolve(s ? t.options.cwd : "", i)), i; } __name$3(ot, "ot"); function Yt(t) { return ot(t) || ot(t, true); } __name$3(Yt, "Yt"); it.exports = Yt; }); var ut = l((qe, P) => { var C = /([()\][%!^"`<>&|;, *?])/g; function Vt(t) { return t = t.replace(C, "^$1"), t; } __name$3(Vt, "Vt"); function Jt(t, e) { return t = `${t}`, t = t.replace(/(\\*)"/g, '$1$1\\"'), t = t.replace(/(\\*)$/, "$1$1"), t = `"${t}"`, t = t.replace(C, "^$1"), e && (t = t.replace(C, "^$1")), t; } __name$3(Jt, "Jt"); P.exports.command = Vt; P.exports.argument = Jt; }); var lt = l((Ie, at) => { at.exports = /^#!(.*)/; }); var dt = l((Le, pt) => { var Qt = lt(); pt.exports = (t = "") => { let e = t.match(Qt); if (!e) return null; let [n, r] = e[0].replace(/#! ?/, "").split(" "), s = n.split("/").pop(); return s === "env" ? r : r ? `${s} ${r}` : s; }; }); var ht = l((je, ft) => { var O = h("fs"), Zt = dt(); function te(t) { let n = Buffer.alloc(150), r; try { r = O.openSync(t, "r"), O.readSync(r, n, 0, 150, 0), O.closeSync(r); } catch { } return Zt(n.toString()); } __name$3(te, "te"); ft.exports = te; }); var wt = l((Fe, Et) => { var ee = h("path"), mt = ct(), gt = ut(), ne = ht(), re = process.platform === "win32", se = /\.(?:com|exe)$/i, oe = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; function ie(t) { t.file = mt(t); let e = t.file && ne(t.file); return e ? (t.args.unshift(t.file), t.command = e, mt(t)) : t.file; } __name$3(ie, "ie"); function ce(t) { if (!re) return t; let e = ie(t), n = !se.test(e); if (t.options.forceShell || n) { let r = oe.test(e); t.command = ee.normalize(t.command), t.command = gt.command(t.command), t.args = t.args.map((o) => gt.argument(o, r)); let s = [t.command].concat(t.args).join(" "); t.args = ["/d", "/s", "/c", `"${s}"`], t.command = process.env.comspec || "cmd.exe", t.options.windowsVerbatimArguments = true; } return t; } __name$3(ce, "ce"); function ue(t, e, n) { e && !Array.isArray(e) && (n = e, e = null), e = e ? e.slice(0) : [], n = Object.assign({}, n); let r = { command: t, args: e, options: n, file: void 0, original: { command: t, args: e } }; return n.shell ? r : ce(r); } __name$3(ue, "ue"); Et.exports = ue; }); var bt = l((ze, vt) => { var S = process.platform === "win32"; function k(t, e) { return Object.assign(new Error(`${e} ${t.command} ENOENT`), { code: "ENOENT", errno: "ENOENT", syscall: `${e} ${t.command}`, path: t.command, spawnargs: t.args }); } __name$3(k, "k"); function ae(t, e) { if (!S) return; let n = t.emit; t.emit = function(r, s) { if (r === "exit") { let o = xt(s, e); if (o) return n.call(t, "error", o); } return n.apply(t, arguments); }; } __name$3(ae, "ae"); function xt(t, e) { return S && t === 1 && !e.file ? k(e.original, "spawn") : null; } __name$3(xt, "xt"); function le(t, e) { return S && t === 1 && !e.file ? k(e.original, "spawnSync") : null; } __name$3(le, "le"); vt.exports = { hookChildProcess: ae, verifyENOENT: xt, verifyENOENTSync: le, notFoundError: k }; }); var Ct = l((He, E) => { var yt = h("child_process"), T = wt(), A = bt(); function _t(t, e, n) { let r = T(t, e, n), s = yt.spawn(r.command, r.args, r.options); return A.hookChildProcess(s, r), s; } __name$3(_t, "_t"); function pe(t, e, n) { let r = T(t, e, n), s = yt.spawnSync(r.command, r.args, r.options); return s.error = s.error || A.verifyENOENTSync(s.status, r), s; } __name$3(pe, "pe"); E.exports = _t; E.exports.spawn = _t; E.exports.sync = pe; E.exports._parse = T; E.exports._enoent = A; }); var Lt = /^path$/i; var q = { key: "PATH", value: "" }; function jt(t) { for (let e in t) { if (!Object.prototype.hasOwnProperty.call(t, e) || !Lt.test(e)) continue; let n = t[e]; return n ? { key: e, value: n } : q; } return q; } __name$3(jt, "jt"); function Ft(t, e) { let n = e.value.split(delimiter), r = t, s; do n.push(resolve(r, "node_modules", ".bin")), s = r, r = dirname(r); while (r !== s); return { key: e.key, value: n.join(delimiter) }; } __name$3(Ft, "Ft"); function I(t, e) { let n = { ...process.env, ...e }, r = Ft(t, jt(n)); return n[r.key] = r.value, n; } __name$3(I, "I"); var L = /* @__PURE__ */ __name$3((t) => { let e = t.length, n = new PassThrough(), r = /* @__PURE__ */ __name$3(() => { --e === 0 && n.emit("end"); }, "r"); for (let s of t) s.pipe(n, { end: false }), s.on("end", r); return n; }, "L"); var Pt = Nt(Ct(), 1); var x = class extends Error { static { __name$3(this, "x"); } result; output; get exitCode() { if (this.result.exitCode !== null) return this.result.exitCode; } constructor(e, n) { super(`Process exited with non-zero status (${e.exitCode})`), this.result = e, this.output = n; } }; var ge = { timeout: void 0, persist: false }; var Ee = { windowsHide: true }; function we(t, e) { return { command: normalize(t), args: e ?? [] }; } __name$3(we, "we"); function xe(t) { let e = new AbortController(); for (let n of t) { if (n.aborted) return e.abort(), n; let r = /* @__PURE__ */ __name$3(() => { e.abort(n.reason); }, "r"); n.addEventListener("abort", r, { signal: e.signal }); } return e.signal; } __name$3(xe, "xe"); var R = class { static { __name$3(this, "R"); } _process; _aborted = false; _options; _command; _args; _resolveClose; _processClosed; _thrownError; get process() { return this._process; } get pid() { return this._process?.pid; } get exitCode() { if (this._process && this._process.exitCode !== null) return this._process.exitCode; } constructor(e, n, r) { this._options = { ...ge, ...r }, this._command = e, this._args = n ?? [], this._processClosed = new Promise((s) => { this._resolveClose = s; }); } kill(e) { return this._process?.kill(e) === true; } get aborted() { return this._aborted; } get killed() { return this._process?.killed === true; } pipe(e, n, r) { return be(e, n, { ...r, stdin: this }); } async *[Symbol.asyncIterator]() { let e = this._process; if (!e) return; let n = []; this._streamErr && n.push(this._streamErr), this._streamOut && n.push(this._streamOut); let r = L(n), s = me.createInterface({ input: r }); for await (let o of s) yield o.toString(); if (await this._processClosed, e.removeAllListeners(), this._thrownError) throw this._thrownError; if (this._options?.throwOnError && this.exitCode !== 0 && this.exitCode !== void 0) throw new x(this); } async _waitForOutput() { let e = this._process; if (!e) throw new Error("No process was started"); let n = "", r = ""; if (this._streamOut) for await (let o of this._streamOut) r += o.toString(); if (this._streamErr) for await (let o of this._streamErr) n += o.toString(); if (await this._processClosed, this._options?.stdin && await this._options.stdin, e.removeAllListeners(), this._thrownError) throw this._thrownError; let s = { stderr: n, stdout: r, exitCode: this.exitCode }; if (this._options.throwOnError && this.exitCode !== 0 && this.exitCode !== void 0) throw new x(this, s); return s; } then(e, n) { return this._waitForOutput().then(e, n); } _streamOut; _streamErr; spawn() { let e = cwd(), n = this._options, r = { ...Ee, ...n.nodeOptions }, s = []; this._resetState(), n.timeout !== void 0 && s.push(AbortSignal.timeout(n.timeout)), n.signal !== void 0 && s.push(n.signal), n.persist === true && (r.detached = true), s.length > 0 && (r.signal = xe(s)), r.env = I(e, r.env); let { command: o, args: i } = we(this._command, this._args), a = (0, Pt._parse)(o, i, r), c = spawn( a.command, a.args, a.options ); if (c.stderr && (this._streamErr = c.stderr), c.stdout && (this._streamOut = c.stdout), this._process = c, c.once("error", this._onError), c.once("close", this._onClose), n.stdin !== void 0 && c.stdin && n.stdin.process) { let { stdout: u } = n.stdin.process; u && u.pipe(c.stdin); } } _resetState() { this._aborted = false, this._processClosed = new Promise((e) => { this._resolveClose = e; }), this._thrownError = void 0; } _onError = /* @__PURE__ */ __name$3((e) => { if (e.name === "AbortError" && (!(e.cause instanceof Error) || e.cause.name !== "TimeoutError")) { this._aborted = true; return; } this._thrownError = e; }, "_onError"); _onClose = /* @__PURE__ */ __name$3(() => { this._resolveClose && this._resolveClose(); }, "_onClose"); }; var ve = /* @__PURE__ */ __name$3((t, e, n) => { let r = new R(t, e, n); return r.spawn(), r; }, "ve"); var be = ve; var __defProp$2 = Object.defineProperty; var __name$2 = (target, value) => __defProp$2(target, "name", { value, configurable: true }); async function detectPackageManager(cwd = process$1.cwd()) { const result = await detect({ cwd, onUnknown(packageManager) { console.warn("[@antfu/install-pkg] Unknown packageManager:", packageManager); return void 0; } }); return result?.agent || null; } __name$2(detectPackageManager, "detectPackageManager"); async function installPackage(names, options = {}) { const detectedAgent = options.packageManager || await detectPackageManager(options.cwd) || "npm"; const [agent] = detectedAgent.split("@"); if (!Array.isArray(names)) names = [names]; const args = (typeof options.additionalArgs === "function" ? options.additionalArgs(agent, detectedAgent) : options.additionalArgs) || []; if (options.preferOffline) { if (detectedAgent === "yarn@berry") args.unshift("--cached"); else args.unshift("--prefer-offline"); } if (agent === "pnpm") { args.unshift( /** * Prevent pnpm from removing installed devDeps while `NODE_ENV` is `production` * @see https://pnpm.io/cli/install#--prod--p */ "--prod=false" ); if (existsSync(resolve$1(options.cwd ?? process$1.cwd(), "pnpm-workspace.yaml"))) { args.unshift("-w"); } } return ve( agent, [ agent === "yarn" ? "add" : "install", options.dev ? "-D" : "", ...args, ...names ].filter(Boolean), { nodeOptions: { stdio: options.silent ? "ignore" : "inherit", cwd: options.cwd }, throwOnError: true } ); } __name$2(installPackage, "installPackage"); async function uninstallPackage(names, options = {}) { const detectedAgent = options.packageManager || await detectPackageManager(options.cwd) || "npm"; const [agent] = detectedAgent.split("@"); if (!Array.isArray(names)) names = [names]; const args = options.additionalArgs || []; if (agent === "pnpm" && existsSync(resolve$1(options.cwd ?? process$1.cwd(), "pnpm-workspace.yaml"))) args.unshift("-w"); return ve( agent, [ agent === "yarn" ? "remove" : "uninstall", options.dev ? "-D" : "", ...args, ...names ].filter(Boolean), { nodeOptions: { stdio: options.silent ? "ignore" : "inherit", cwd: options.cwd }, throwOnError: true } ); } __name$2(uninstallPackage, "uninstallPackage"); var __defProp$1 = Object.defineProperty; var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true }); const isObject = /* @__PURE__ */ __name$1((value) => { const type = typeof value; return value !== null && (type === "object" || type === "function"); }, "isObject"); const isEmptyObject = /* @__PURE__ */ __name$1((value) => isObject(value) && Object.keys(value).length === 0, "isEmptyObject"); const disallowedKeys = /* @__PURE__ */ new Set([ "__proto__", "prototype", "constructor" ]); const digits = new Set("0123456789"); function getPathSegments(path) { const parts = []; let currentSegment = ""; let currentPart = "start"; let isIgnoring = false; for (const character of path) { switch (character) { case "\\": { if (currentPart === "index") { throw new Error("Invalid character in an index"); } if (currentPart === "indexEnd") { throw new Error("Invalid character after an index"); } if (isIgnoring) { currentSegment += character; } currentPart = "property"; isIgnoring = !isIgnoring; break; } case ".": { if (currentPart === "index") { throw new Error("Invalid character in an index"); } if (currentPart === "indexEnd") { currentPart = "property"; break; } if (isIgnoring) { isIgnoring = false; currentSegment += character; break; } if (disallowedKeys.has(currentSegment)) { return []; } parts.push(currentSegment); currentSegment = ""; currentPart = "property"; break; } case "[": { if (currentPart === "index") { throw new Error("Invalid character in an index"); } if (currentPart === "indexEnd") { currentPart = "index"; break; } if (isIgnoring) { isIgnoring = false; currentSegment += character; break; } if (currentPart === "property") { if (disallowedKeys.has(currentSegment)) { return []; } parts.push(currentSegment); currentSegment = ""; } currentPart = "index"; break; } case "]": { if (currentPart === "index") { parts.push(Number.parseInt(currentSegment, 10)); currentSegment = ""; currentPart = "indexEnd"; break; } if (currentPart === "indexEnd") { throw new Error("Invalid character after an index"); } } default: { if (currentPart === "index" && !digits.has(character)) { throw new Error("Invalid character in an index"); } if (currentPart === "indexEnd") { throw new Error("Invalid character after an index"); } if (currentPart === "start") { currentPart = "property"; } if (isIgnoring) { isIgnoring = false; currentSegment += "\\"; } currentSegment += character; } } } if (isIgnoring) { currentSegment += "\\"; } switch (currentPart) { case "property": { if (disallowedKeys.has(currentSegment)) { return []; } parts.push(currentSegment); break; } case "index": { throw new Error("Index was not closed"); } case "start": { parts.push(""); break; } } return parts; } __name$1(getPathSegments, "getPathSegments"); function isStringIndex(object, key) { if (typeof key !== "number" && Array.isArray(object)) { const index = Number.parseInt(key, 10); return Number.isInteger(index) && object[index] === object[key]; } return false; } __name$1(isStringIndex, "isStringIndex"); function assertNotStringIndex(object, key) { if (isStringIndex(object, key)) { throw new Error("Cannot use string index"); } } __name$1(assertNotStringIndex, "assertNotStringIndex"); function getProperty(object, path, value) { if (!isObject(object) || typeof path !== "string") { return value === void 0 ? object : value; } const pathArray = getPathSegments(path); if (pathArray.length === 0) { return value; } for (let index = 0; index < pathArray.length; index++) { const key = pathArray[index]; if (isStringIndex(object, key)) { object = index === pathArray.length - 1 ? void 0 : null; } else { object = object[key]; } if (object === void 0 || object === null) { if (index !== pathArray.length - 1) { return value; } break; } } return object === void 0 ? value : object; } __name$1(getProperty, "getProperty"); function setProperty(object, path, value) { if (!isObject(object) || typeof path !== "string") { return object; } const root = object; const pathArray = getPathSegments(path); for (let index = 0; index < pathArray.length; index++) { const key = pathArray[index]; assertNotStringIndex(object, key); if (index === pathArray.length - 1) { object[key] = value; } else if (!isObject(object[key])) { object[key] = typeof pathArray[index + 1] === "number" ? [] : {}; } object = object[key]; } return root; } __name$1(setProperty, "setProperty"); function deleteProperty(object, path) { if (!isObject(object) || typeof path !== "string") { return false; } const pathArray = getPathSegments(path); for (let index = 0; index < pathArray.length; index++) { const key = pathArray[index]; assertNotStringIndex(object, key); if (index === pathArray.length - 1) { delete object[key]; return true; } object = object[key]; if (!isObject(object)) { return false; } } } __name$1(deleteProperty, "deleteProperty"); function hasProperty(object, path) { if (!isObject(object) || typeof path !== "string") { return false; } const pathArray = getPathSegments(path); if (pathArray.length === 0) { return false; } for (const key of pathArray) { if (!isObject(object) || !(key in object) || isStringIndex(object, key)) { return false; } object = object[key]; } return true; } __name$1(hasProperty, "hasProperty"); function escapePath(path) { if (typeof path !== "string") { throw new TypeError("Expected a string"); } return path.replaceAll(/[\\.[]/g, "\\$&"); } __name$1(escapePath, "escapePath"); function entries(value) { const result = Object.entries(value); if (Array.isArray(value)) { return result.map(([key, value2]) => [Number(key), value2]); } return result; } __name$1(entries, "entries"); function stringifyPath(pathSegments) { let result = ""; for (let [index, segment] of entries(pathSegments)) { if (typeof segment === "number") { result += `[${segment}]`; } else { segment = escapePath(segment); result += index === 0 ? segment : `.${segment}`; } } return result; } __name$1(stringifyPath, "stringifyPath"); function* deepKeysIterator(object, currentPath = []) { if (!isObject(object) || isEmptyObject(object)) { if (currentPath.length > 0) { yield stringifyPath(currentPath); } return; } for (const [key, value] of entries(object)) { yield* deepKeysIterator(value, [...currentPath, key]); } } __name$1(deepKeysIterator, "deepKeysIterator"); function deepKeys(object) { return [...deepKeysIterator(object)]; } __name$1(deepKeys, "deepKeys"); const isNode = typeof process.stdout < "u" && !process.versions.deno && !globalThis.window; var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); const PackageJsonFileCache = /* @__PURE__ */ new Map(); class PackageJsonValidationError extends Error { static { __name(this, "PackageJsonValidationError"); } constructor(warnings) { super(`The following warnings were encountered while normalizing package data: - ${warnings.join("\n- ")}`); this.name = "PackageJsonValidationError"; } } const normalizeInput = /* @__PURE__ */ __name((input, strict, ignoreWarnings = []) => { const warnings = []; normalizeData( input, (message) => { warnings.push(message); }, strict ); if (strict && warnings.length > 0) { const filteredWarnings = warnings.filter( (warning) => !ignoreWarnings.some((pattern) => { if (pattern instanceof RegExp) { return pattern.test(warning); } return pattern === warning; }) ); if (filteredWarnings.length > 0) { throw new PackageJsonValidationError(filteredWarnings); } } return input; }, "normalizeInput"); const findPackageJson = /* @__PURE__ */ __name(async (cwd, options = {}) => { const findUpConfig = { type: "file" }; if (cwd) { findUpConfig.cwd = cwd; } const filePath = await findUp("package.json", findUpConfig); if (!filePath) { throw new NotFoundError("No such file or directory, for package.json found."); } const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : PackageJsonFileCache; if (options.cache && cache.has(filePath)) { return cache.get(filePath); } const packageJson = await readJson(filePath); normalizeInput(packageJson, options.strict ?? false, options.ignoreWarnings); const output = { packageJson, path: filePath }; cache.set(filePath, output); return output; }, "findPackageJson"); const findPackageJsonSync = /* @__PURE__ */ __name((cwd, options = {}) => { const findUpConfig = { type: "file" }; if (cwd) { findUpConfig.cwd = cwd; } const filePath = findUpSync("package.json", findUpConfig); if (!filePath) { throw new NotFoundError("No such file or directory, for package.json found."); } const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : PackageJsonFileCache; if (options.cache && cache.has(filePath)) { return cache.get(filePath); } const packageJson = readJsonSync(filePath); normalizeInput(packageJson, options.strict ?? false, options.ignoreWarnings); const output = { packageJson, path: filePath }; cache.set(filePath, output); return output; }, "findPackageJsonSync"); const writePackageJson = /* @__PURE__ */ __name(async (data, options = {}) => { const { cwd, ...writeOptions } = options; const directory = toPath(options.cwd ?? process.cwd()); await writeJson(join(directory, "package.json"), data, writeOptions); }, "writePackageJson"); const writePackageJsonSync = /* @__PURE__ */ __name((data, options = {}) => { const { cwd, ...writeOptions } = options; const directory = toPath(options.cwd ?? process.cwd()); writeJsonSync(join(directory, "package.json"), data, writeOptions); }, "writePackageJsonSync"); const parsePackageJson = /* @__PURE__ */ __name((packageFile, options) => { const isObject = packageFile !== null && typeof packageFile === "object" && !Array.isArray(packageFile); const isString = typeof packageFile === "string"; if (!isObject && !isString) { throw new TypeError("`packageFile` should be either an `object` or a `string`."); } const json = isObject ? structuredClone(packageFile) : ( // eslint-disable-next-line security/detect-non-literal-fs-filename existsSync(packageFile) ? readJsonSync(packageFile) : parseJson(packageFile) ); normalizeInput(json, options?.strict ?? false, options?.ignoreWarnings); return json; }, "parsePackageJson"); const getPackageJsonProperty = /* @__PURE__ */ __name((packageJson, property, defaultValue) => getProperty(packageJson, property, defaultValue), "getPackageJsonProperty"); const hasPackageJsonProperty = /* @__PURE__ */ __name((packageJson, property) => hasProperty(packageJson, property), "hasPackageJsonProperty"); const hasPackageJsonAnyDependency = /* @__PURE__ */ __name((packageJson, arguments_, options) => { const dependencies = getProperty(packageJson, "dependencies", {}); const devDependencies = getProperty(packageJson, "devDependencies", {}); const peerDependencies = getProperty(packageJson, "peerDependencies", {}); const allDependencies = { ...dependencies, ...devDependencies, ...options?.peerDeps === false ? {} : peerDependencies }; for (const argument of arguments_) { if (hasProperty(allDependencies, argument)) { return true; } } return false; }, "hasPackageJsonAnyDependency"); const ensurePackages = /* @__PURE__ */ __name(async (packageJson, packages, installKey = "dependencies", options = {}) => { if (process.env.CI || isNode && !process.stdout?.isTTY) { console.warn("Skipping package installation because the process is not interactive."); return; } const dependencies = getProperty(packageJson, "dependencies", {}); const devDependencies = getProperty(packageJson, "devDependencies", {}); const peerDependencies = getProperty(packageJson, "peerDependencies", {}); const nonExistingPackages = []; const config = { deps: true, devDeps: true, peerDeps: false, ...options }; for (const packageName of packages) { if (config.deps && hasProperty(dependencies, packageName) || config.devDeps && hasProperty(devDependencies, packageName) || config.peerDeps && hasProperty(peerDependencies, packageName)) { continue; } nonExistingPackages.push(packageName); } if (nonExistingPackages.length === 0) { return; } if (typeof config.confirm?.message === "function") { config.confirm.message = config.confirm.message(nonExistingPackages); } if (config.confirm?.message === void 0) { const message = `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`; if (config.confirm === void 0) { config.confirm = { message }; } else { config.confirm.message = message; } } const answer = await confirm(config.confirm); if (!answer) { return; } await installPackage(nonExistingPackages, { ...config.installPackage, cwd: config.cwd ? toPath(config.cwd) : void 0, dev: installKey === "devDependencies" }); }, "ensurePackages"); export { ensurePackages, findPackageJson, findPackageJsonSync, getPackageJsonProperty, hasPackageJsonAnyDependency, hasPackageJsonProperty, parsePackageJson, writePackageJson, writePackageJsonSync };