2

I'm working on an npm package initializer, that is, a program that runs when the user runs the npm init <my-package-initializer> command.

npm is not the only package manager for Node.js any more, yarn is also quite popular and pnpm is a personal favorite of mine and I want to support all three. The easy way is to ask the user which package manager they prefer or provide a command-line switch like CRA does.

But the user has already shown their preference by running, say, yarn create instead of npm init. It feels annoying to ask again. We could just check if yarn or pnpm is our parent process.

Is there a cross-platform way to get this information?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
cyco130
  • 4,654
  • 25
  • 34

1 Answers1

0

For future googlers, I ended up using the following snippet. I use it for picking the default choice but I still ask the user explicitly for their package manager preference, better safe than sorry.

function getPackageManager() {
    // This environment variable is set by npm and yarn but pnpm seems less consistent
    const agent = process.env.npm_config_user_agent;

    if (!agent) {
        // This environment variable is set on Linux but I'm not sure about other OSes.
        const parent = process.env._;

        if (!parent) {
            // No luck, assume npm
            return "npm";
        }

        if (parent.endsWith("pnpx") || parent.endsWith("pnpm")) return "pnpm";
        if (parent.endsWith("yarn")) return "yarn";

        // Assume npm for anything else
        return "npm";
    }

    const [program] = agent.split("/");

    if (program === "yarn") return "yarn";
    if (program === "pnpm") return "pnpm";

    // Assume npm
    return "npm";
}
cyco130
  • 4,654
  • 25
  • 34