123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- import { existsSync } from 'node:fs';
- import { readFile } from 'node:fs/promises';
- import { normalize, resolve, join } from 'pathe';
- import { createRequire } from 'node:module';
- import { withTrailingSlash } from 'ufo';
- async function findup(cwd, match, options = {}) {
- const segments = normalize(cwd).split("/");
- while (segments.length > 0) {
- const path = segments.join("/");
- const result = await match(path);
- if (result || !options.includeParentDirs) {
- return result;
- }
- segments.pop();
- }
- }
- function cached(fn) {
- let v;
- return () => {
- if (v === void 0) {
- v = fn().then((r) => {
- v = r;
- return v;
- });
- }
- return v;
- };
- }
- const importExeca = cached(() => import('execa').then((r) => r.execa));
- const hasCorepack = cached(async () => {
- try {
- const execa = await importExeca();
- await execa("corepack", ["--version"]);
- return true;
- } catch {
- return false;
- }
- });
- async function executeCommand(command, args, options = {}) {
- const execaArgs = command === "npm" || command === "bun" || !await hasCorepack() ? [command, args] : ["corepack", [command, ...args]];
- const execa = await importExeca();
- await execa(execaArgs[0], execaArgs[1], {
- cwd: resolve(options.cwd || process.cwd()),
- stdio: options.silent ? "pipe" : "inherit"
- });
- }
- const NO_PACKAGE_MANAGER_DETECTED_ERROR_MSG = "No package manager auto-detected.";
- async function resolveOperationOptions(options = {}) {
- const cwd = options.cwd || process.cwd();
- const packageManager = (typeof options.packageManager === "string" ? packageManagers.find((pm) => pm.name === options.packageManager) : options.packageManager) || await detectPackageManager(options.cwd || process.cwd());
- if (!packageManager) {
- throw new Error(NO_PACKAGE_MANAGER_DETECTED_ERROR_MSG);
- }
- return {
- cwd,
- silent: options.silent ?? false,
- packageManager,
- dev: options.dev ?? false,
- workspace: options.workspace
- };
- }
- function getWorkspaceArgs(options) {
- if (!options.workspace) {
- return [];
- }
- const workspacePkg = typeof options.workspace === "string" && options.workspace !== "" ? options.workspace : void 0;
- if (options.packageManager.name === "pnpm") {
- return workspacePkg ? ["--dir", workspacePkg] : ["--workspace-root"];
- }
- if (options.packageManager.name === "npm") {
- return workspacePkg ? ["-w", workspacePkg] : ["--workspaces"];
- }
- if (options.packageManager.name === "yarn") {
- if (!options.packageManager.majorVersion || options.packageManager.majorVersion === "1") {
- return workspacePkg ? ["--cwd", workspacePkg] : ["-W"];
- } else {
- return workspacePkg ? ["workspace", workspacePkg] : [];
- }
- }
- return [];
- }
- function doesDependencyExist(name, options) {
- const require = createRequire(withTrailingSlash(options.cwd));
- try {
- const resolvedPath = require.resolve(name);
- return resolvedPath.startsWith(options.cwd);
- } catch {
- return false;
- }
- }
- const packageManagers = [
- { name: "npm", command: "npm", lockFile: "package-lock.json" },
- {
- name: "pnpm",
- command: "pnpm",
- lockFile: "pnpm-lock.yaml",
- files: ["pnpm-workspace.yaml"]
- },
- {
- name: "bun",
- command: "bun",
- lockFile: "bun.lockb"
- },
- {
- name: "yarn",
- command: "yarn",
- majorVersion: "1.0.0",
- lockFile: "yarn.lock"
- },
- {
- name: "yarn",
- command: "yarn",
- majorVersion: "3.0.0",
- lockFile: "yarn.lock",
- files: [".yarnrc.yml"]
- }
- ];
- async function detectPackageManager(cwd, options = {}) {
- const detected = await findup(
- cwd,
- async (path) => {
- if (!options.ignorePackageJSON) {
- const packageJSONPath = join(path, "package.json");
- if (existsSync(packageJSONPath)) {
- const packageJSON = JSON.parse(
- await readFile(packageJSONPath, "utf8")
- );
- if (packageJSON?.packageManager) {
- const [name, version = "0.0.0"] = packageJSON.packageManager.split("@");
- const majorVersion = version.split(".")[0];
- const packageManager = packageManagers.find(
- (pm) => pm.name === name && pm.majorVersion === majorVersion
- ) || packageManagers.find((pm) => pm.name === name);
- return {
- ...packageManager,
- name,
- command: name,
- version,
- majorVersion
- };
- }
- }
- }
- if (!options.ignoreLockFile) {
- for (const packageManager of packageManagers) {
- const detectionsFiles = [
- packageManager.lockFile,
- ...packageManager.files || []
- ].filter(Boolean);
- if (detectionsFiles.some((file) => existsSync(resolve(path, file)))) {
- return {
- ...packageManager
- };
- }
- }
- }
- },
- {
- includeParentDirs: options.includeParentDirs ?? true
- }
- );
- return detected;
- }
- async function installDependencies(options = {}) {
- const resolvedOptions = await resolveOperationOptions(options);
- await executeCommand(resolvedOptions.packageManager.command, ["install"], {
- cwd: resolvedOptions.cwd,
- silent: resolvedOptions.silent
- });
- }
- async function addDependency(name, options = {}) {
- const resolvedOptions = await resolveOperationOptions(options);
- const names = Array.isArray(name) ? name : [name];
- const args = (resolvedOptions.packageManager.name === "yarn" ? [
- ...getWorkspaceArgs(resolvedOptions),
- "add",
- resolvedOptions.dev ? "-D" : "",
- ...names
- ] : [
- resolvedOptions.packageManager.name === "npm" ? "install" : "add",
- ...getWorkspaceArgs(resolvedOptions),
- resolvedOptions.dev ? "-D" : "",
- ...names
- ]).filter(Boolean);
- await executeCommand(resolvedOptions.packageManager.command, args, {
- cwd: resolvedOptions.cwd,
- silent: resolvedOptions.silent
- });
- }
- async function addDevDependency(name, options = {}) {
- await addDependency(name, { ...options, dev: true });
- }
- async function removeDependency(name, options = {}) {
- const resolvedOptions = await resolveOperationOptions(options);
- const args = (resolvedOptions.packageManager.name === "yarn" ? [
- ...getWorkspaceArgs(resolvedOptions),
- "remove",
- resolvedOptions.dev ? "-D" : "",
- name
- ] : [
- resolvedOptions.packageManager.name === "npm" ? "uninstall" : "remove",
- ...getWorkspaceArgs(resolvedOptions),
- resolvedOptions.dev ? "-D" : "",
- name
- ]).filter(Boolean);
- await executeCommand(resolvedOptions.packageManager.command, args, {
- cwd: resolvedOptions.cwd,
- silent: resolvedOptions.silent
- });
- }
- async function ensureDependencyInstalled(name, options = {}) {
- const resolvedOptions = await resolveOperationOptions(options);
- const dependencyExists = doesDependencyExist(name, resolvedOptions);
- if (dependencyExists) {
- return true;
- }
- await addDependency(name, resolvedOptions);
- }
- export { addDependency, addDevDependency, detectPackageManager, ensureDependencyInstalled, installDependencies, packageManagers, removeDependency };
|