Skip to content

Commit

Permalink
Infer package manager from user agent
Browse files Browse the repository at this point in the history
  • Loading branch information
Shaun Lloyd committed Nov 28, 2023
1 parent 4d66fc1 commit 6379ff8
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
36 changes: 36 additions & 0 deletions code/lib/cli/src/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,40 @@ describe('Helpers', () => {
}).toThrowError("Couldn't find any official storybook packages in package.json");
});
});

describe('inferPackageManagerFromUserAgent', () => {
afterEach(() => {
delete process.env.npm_config_user_agent;
});

it('should return undefined for invalid user agent', () => {
process.env.npm_config_user_agent = '';
expect(helpers.inferPackageManagerFromUserAgent()).toBeUndefined();
});

it('should infer pnpm from user agent', () => {
process.env.npm_config_user_agent = 'pnpm/7.4.0';
expect(helpers.inferPackageManagerFromUserAgent()).toBe('pnpm');
});

it('should infer npm from user agent', () => {
process.env.npm_config_user_agent = 'npm/7.24.0';
expect(helpers.inferPackageManagerFromUserAgent()).toBe('npm');
});

it('should infer yarn 1 from user agent', () => {
process.env.npm_config_user_agent = 'yarn/1.22.11';
expect(helpers.inferPackageManagerFromUserAgent()).toBe('yarn1');
});

it('should infer yarn 2 from user agent', () => {
process.env.npm_config_user_agent = 'yarn/2.4.0';
expect(helpers.inferPackageManagerFromUserAgent()).toBe('yarn2');
});

it('should return undefined for unknown package manager', () => {
process.env.npm_config_user_agent = 'unknown';
expect(helpers.inferPackageManagerFromUserAgent()).toBeUndefined();
});
});
});
27 changes: 27 additions & 0 deletions code/lib/cli/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
JsPackageManager,
PackageJson,
PackageJsonWithDepsAndDevDeps,
PackageManagerName,
} from './js-package-manager';
import type { SupportedFrameworks, SupportedRenderers } from './project_types';
import { SupportedLanguage } from './project_types';
Expand Down Expand Up @@ -303,3 +304,29 @@ export function getStorybookVersionSpecifier(packageJson: PackageJsonWithDepsAnd
export async function isNxProject() {
return findUp.sync('nx.json');
}

/**
* Infer the package manager based on the command the user is running.
* Each package manager sets the `npm_config_user_agent` environment variable with its name and version e.g. "npm/7.24.0"
* Which is really useful when invoking commands via npx/pnpx/yarn create/etc.
*/
export function inferPackageManagerFromUserAgent(): PackageManagerName {
const userAgent = process.env.npm_config_user_agent;
if (!userAgent) return undefined;
const packageSpec = userAgent.split(' ')[0];
const [pkgMgrName, pkgMgrVersion] = packageSpec.split('/');

if (pkgMgrName === 'pnpm') {
return 'pnpm';
}

if (pkgMgrName === 'npm') {
return 'npm';
}

if (pkgMgrName === 'yarn') {
return `yarn${pkgMgrVersion?.startsWith('1.') ? '1' : '2'}`;
}

return undefined;
}
7 changes: 5 additions & 2 deletions code/lib/cli/src/initiate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import boxen from 'boxen';
import { readdirSync } from 'fs-extra';
import { installableProjectTypes, ProjectType } from './project_types';
import { detect, isStorybookInstantiated, detectLanguage, detectPnp } from './detect';
import { commandLog, codeLog, paddedLog } from './helpers';
import { commandLog, codeLog, paddedLog, inferPackageManagerFromUserAgent } from './helpers';
import angularGenerator from './generators/ANGULAR';
import emberGenerator from './generators/EMBER';
import reactGenerator from './generators/REACT';
Expand Down Expand Up @@ -257,7 +257,10 @@ async function doInitiate(
const isEmptyDir =
cwdFolderEntries.length === 0 || cwdFolderEntries.every((entry) => entry.startsWith('.'));

const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr });
const packageManager = JsPackageManagerFactory.getPackageManager({
force: pkgMgr || inferPackageManagerFromUserAgent(),
});

const welcomeMessage = 'storybook init - the simplest way to add a Storybook to your project.';
logger.log(chalk.inverse(`\n ${welcomeMessage} \n`));

Expand Down

0 comments on commit 6379ff8

Please sign in to comment.