UNPKG

op-pkg

Version:
153 lines (148 loc) 4.32 kB
import fs, { existsSync } from 'node:fs'; import { resolve, dirname, join, win32 } from 'node:path'; import process from 'node:process'; import { x } from 'tinyexec'; import { detect } from 'package-manager-detector/detect'; import fsp from 'node:fs/promises'; import { createRequire } from 'node:module'; import { findUp } from 'find-up'; import { interopDefault, resolvePathSync } from 'mlly'; async function detectPackageManager(cwd = process.cwd()) { const result = await detect({ cwd, onUnknown(packageManager) { console.warn("[op-pkg] Unknown packageManager:", packageManager); return void 0; } }); return result?.agent || null; } 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" && existsSync(resolve(options.cwd ?? process.cwd(), "pnpm-workspace.yaml"))) { args.unshift( "-w", /** * Prevent pnpm from removing installed devDeps while `NODE_ENV` is `production` * @see https://pnpm.io/cli/install#--prod--p */ "--prod=false" ); } return x( agent, [ agent === "yarn" ? "add" : "install", options.dev ? "-D" : "", ...args, ...names ].filter(Boolean), { nodeOptions: { stdio: options.silent ? "ignore" : "inherit", cwd: options.cwd }, throwOnError: true } ); } function _resolve(path, options = {}) { if (options.platform === "auto" || !options.platform) options.platform = process.platform === "win32" ? "win32" : "posix"; if (process.versions.pnp) { const paths = options.paths || []; if (paths.length === 0) paths.push(process.cwd()); const targetRequire = createRequire(import.meta.url); try { return targetRequire.resolve(path, { paths }); } catch { } } const modulePath = resolvePathSync(path, { url: options.paths }); if (options.platform === "win32") return win32.normalize(modulePath); return modulePath; } function resolveModule(name, options = {}) { try { return _resolve(name, options); } catch { return void 0; } } async function importModule(path) { const i = await import(path); if (i) return interopDefault(i); return i; } function isPackageExists(name, options = {}) { return !!resolvePackage(name, options); } async function getPackageInfo(name, options = {}) { const packageJsonPath = getPackageJsonPath(name, options); if (!packageJsonPath) return; const packageJson = JSON.parse(await fs.promises.readFile(packageJsonPath, "utf8")); return { name, version: packageJson.version, rootPath: dirname(packageJsonPath), packageJsonPath, packageJson }; } async function loadPackageJSON(cwd = process.cwd()) { const path = await findUp("package.json", { cwd }); if (!path || !fs.existsSync(path)) return null; return JSON.parse(await fsp.readFile(path, "utf-8")); } function getPackageJsonPath(name, options = {}) { const entry = resolvePackage(name, options); if (!entry) return; return searchPackageJSON(entry); } function searchPackageJSON(dir) { let packageJsonPath; while (true) { if (!dir) return; const newDir = dirname(dir); if (newDir === dir) return; dir = newDir; packageJsonPath = join(dir, "package.json"); if (fs.existsSync(packageJsonPath)) break; } return packageJsonPath; } function resolvePackage(name, options = {}) { try { return _resolve(`${name}/package.json`, options); } catch { } try { return _resolve(name, options); } catch (e) { if (e.code !== "MODULE_NOT_FOUND" && e.code !== "ERR_MODULE_NOT_FOUND") console.error(e); return false; } } export { detectPackageManager, getPackageInfo, importModule, installPackage, isPackageExists, loadPackageJSON, resolveModule };