1import { execSync } from 'child_process';
2
3export type PackageManagerName = 'npm' | 'pnpm' | 'yarn' | 'bun';
4
5/** Determine which package manager to use for installing dependencies based on how the process was started. */
6export function resolvePackageManager(): PackageManagerName {
7  // Attempt to detect if the user started the command using `yarn` or `pnpm`
8  const userAgent = process.env.npm_config_user_agent;
9
10  if (userAgent?.startsWith('yarn')) {
11    return 'yarn';
12  } else if (userAgent?.startsWith('pnpm')) {
13    return 'pnpm';
14  } else if (userAgent?.startsWith('npm')) {
15    return 'npm';
16  } else if (userAgent?.startsWith('bun')) {
17    return 'bun';
18  }
19
20  // Try availability
21  if (isPackageManagerAvailable('yarn')) {
22    return 'yarn';
23  } else if (isPackageManagerAvailable('pnpm')) {
24    return 'pnpm';
25  } else if (isPackageManagerAvailable('bun')) {
26    return 'bun';
27  }
28
29  return 'npm';
30}
31
32function isPackageManagerAvailable(manager: PackageManagerName): boolean {
33  try {
34    execSync(`${manager} --version`, { stdio: 'ignore' });
35    return true;
36  } catch {}
37  return false;
38}
39
40export function formatRunCommand(manager: PackageManagerName, cmd: string) {
41  switch (manager) {
42    case 'pnpm':
43      return `pnpm run ${cmd}`;
44    case 'yarn':
45      return `yarn ${cmd}`;
46    case 'bun':
47      return `bun run ${cmd}`;
48    case 'npm':
49    default:
50      return `npm run ${cmd}`;
51  }
52}
53