Skip to content

Commit

Permalink
Merge pull request #19425 from storybookjs/pnpm/install
Browse files Browse the repository at this point in the history
CLI: Add pnpm support
  • Loading branch information
shilman authored Oct 18, 2022
2 parents b1c3a0d + 450b2a3 commit 27f6985
Show file tree
Hide file tree
Showing 26 changed files with 642 additions and 126 deletions.
5 changes: 5 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- [Docs modern inline rendering by default](#docs-modern-inline-rendering-by-default)
- [Babel mode v7 by default](#babel-mode-v7-by-default)
- [7.0 feature flags removed](#70-feature-flags-removed)
- [CLI option `--use-npm` deprecated](#cli-option---use-npm-deprecated)
- [Vite builder uses vite config automatically](#vite-builder-uses-vite-config-automatically)
- [Vite cache moved to node_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook)
- [Removed docs.getContainer and getPage parameters](#removed-docsgetcontainer-and-getpage-parameters)
Expand Down Expand Up @@ -524,6 +525,10 @@ In 7.0 we've removed the following feature flags:
| `emotionAlias` | This flag is no longer needed and should be deleted. |
| `breakingChangesV7` | This flag is no longer needed and should be deleted. |

#### CLI option `--use-npm` deprecated

With increased support for more package managers (pnpm), we have introduced the `--package-manager` CLI option. Please use `--package-manager=npm` to force NPM to be used to install dependencies when running Storybook CLI commands. Other valid options are `pnpm`, `yarn1`, and `yarn2` (`yarn2` is for versions 2 and higher).

#### Vite builder uses vite config automatically

When using a [Vite-based framework](#framework-field-mandatory), Storybook will automatically use your `vite.config.(ctm)js` config file starting in 7.0.
Expand Down
20 changes: 17 additions & 3 deletions code/lib/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,26 @@ See the command-line help with `-h` for details.

## [Yarn](https://github.com/yarnpkg/yarn) support

The CLI supports yarn. If you have installed yarn in your system and your project has `yarn.lock` file, it'll detect it and use `yarn` instead of `npm`.
The CLI supports yarn. If you have installed yarn in your system and your project has a `yarn.lock` file, it'll detect it and use `yarn` to install dependencies.

If you don't want to use `yarn` always you can use the `--use-npm` option like this:
If you don't want to use `yarn` always you can use the `--package-manager` option like this:

```sh
npx sb init --use-npm
npx sb init --package-manager=npm
```

If you would like to force a particular version of yarn, you can use the `--package-manager` flag with a value of `yarn1` or `yarn2`.

---

## [PNPM](https://pnpm.io/) support

The CLI supports pnpm. If you have installed pnpm in your system and your project has a `pnpm-lock.yaml` file, it'll detect it and use `pnpm` to install dependencies.

If you don't have a lock file and would like to force pnpm to be used, you can use the `--package-manager` option like this:

```sh
npx sb init --package-manager=pnpm
```

---
Expand Down
4 changes: 3 additions & 1 deletion code/lib/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
"shelljs": "^0.8.5",
"strip-json-comments": "^3.0.1",
"ts-dedent": "^2.0.0",
"update-notifier": "^5.0.1"
"update-notifier": "^5.0.1",
"util-deprecate": "^1.0.2"
},
"devDependencies": {
"@storybook/client-api": "7.0.0-alpha.38",
Expand All @@ -83,6 +84,7 @@
"@types/semver": "^7.3.4",
"@types/shelljs": "^0.8.7",
"@types/update-notifier": "^5.0.0",
"@types/util-deprecate": "^1.0.0",
"strip-json-comments": "^3.1.1",
"typescript": "~4.6.3",
"update-notifier": "^5.0.1"
Expand Down
17 changes: 14 additions & 3 deletions code/lib/cli/src/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import { getStorybookInfo } from '@storybook/core-common';
import { readConfig, writeConfig } from '@storybook/csf-tools';

import { commandLog } from './helpers';
import { JsPackageManagerFactory } from './js-package-manager';
import {
JsPackageManagerFactory,
useNpmWarning,
type PackageManagerName,
} from './js-package-manager';

const logger = console;

Expand Down Expand Up @@ -66,8 +70,15 @@ const getVersionSpecifier = (addon: string) => {
* it will try to use the version specifier matching your current
* Storybook install version.
*/
export async function add(addon: string, options: { useNpm: boolean; skipPostinstall: boolean }) {
const packageManager = JsPackageManagerFactory.getPackageManager(options.useNpm);
export async function add(
addon: string,
options: { useNpm: boolean; packageManager: PackageManagerName; skipPostinstall: boolean }
) {
const { useNpm, packageManager: pkgMgr } = options;
if (useNpm) {
useNpmWarning();
}
const packageManager = JsPackageManagerFactory.getPackageManager({ useNpm, force: pkgMgr });
const packageJson = packageManager.retrievePackageJson();
const [addonName, versionSpecifier] = getVersionSpecifier(addon);

Expand Down
8 changes: 5 additions & 3 deletions code/lib/cli/src/automigrate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import prompts from 'prompts';
import chalk from 'chalk';
import boxen from 'boxen';
import { JsPackageManagerFactory } from '../js-package-manager';
import { JsPackageManagerFactory, type PackageManagerName } from '../js-package-manager';

import { fixes, Fix } from './fixes';

Expand All @@ -12,10 +12,12 @@ interface FixOptions {
fixId?: string;
yes?: boolean;
dryRun?: boolean;
useNpm?: boolean;
force?: PackageManagerName;
}

export const automigrate = async ({ fixId, dryRun, yes }: FixOptions = {}) => {
const packageManager = JsPackageManagerFactory.getPackageManager();
export const automigrate = async ({ fixId, dryRun, yes, useNpm, force }: FixOptions = {}) => {
const packageManager = JsPackageManagerFactory.getPackageManager({ useNpm, force });
const filtered = fixId ? fixes.filter((f) => f.id === fixId) : fixes;

logger.info('🔎 checking possible migrations..');
Expand Down
30 changes: 21 additions & 9 deletions code/lib/cli/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import { sync as readUpSync } from 'read-pkg-up';

import { logger } from '@storybook/node-logger';

import { CommandOptions } from './generators/types';
import { initiate } from './initiate';
import { add } from './add';
import { migrate } from './migrate';
import { extract } from './extract';
import { upgrade } from './upgrade';
import { upgrade, type UpgradeOptions } from './upgrade';
import { repro } from './repro';
import { reproNext } from './repro-next';
import { link } from './link';
Expand All @@ -38,14 +39,15 @@ program
.description('Initialize Storybook into your project.')
.option('-f --force', 'Force add Storybook')
.option('-s --skip-install', 'Skip installing deps')
.option('-N --use-npm', 'Use npm to install deps')
.option('--use-pnp', 'Enable pnp mode')
.option('--package-manager <npm|pnpm|yarn1|yarn2>', 'Force package manager for installing deps')
.option('-N --use-npm', 'Use npm to install deps (deprecated)')
.option('--use-pnp', 'Enable pnp mode for Yarn 2+')
.option('-p --parser <babel | babylon | flow | ts | tsx>', 'jscodeshift parser')
.option('-t --type <type>', 'Add Storybook for a specific project type')
.option('-y --yes', 'Answer yes to all prompts')
.option('-b --builder <builder>', 'Builder library')
.option('-b --builder <webpack5 | vite>', 'Builder library')
.option('-l --linkable', 'Prepare installation for link (contributor helper)')
.action((options) =>
.action((options: CommandOptions) =>
initiate(options, pkg).catch((err) => {
logger.error(err);
process.exit(1);
Expand All @@ -55,9 +57,13 @@ program
program
.command('add <addon>')
.description('Add an addon to your Storybook')
.option('-N --use-npm', 'Use NPM to build the Storybook server')
.option(
'--package-manager <npm|pnpm|yarn1|yarn2>',
'Force package manager for installing dependencies'
)
.option('-N --use-npm', 'Use NPM to install dependencies (deprecated)')
.option('-s --skip-postinstall', 'Skip package specific postinstall config modifications')
.action((addonName, options) => add(addonName, options));
.action((addonName: string, options: any) => add(addonName, options));

program
.command('babelrc')
Expand All @@ -67,12 +73,16 @@ program
program
.command('upgrade')
.description('Upgrade your Storybook packages to the latest')
.option('-N --use-npm', 'Use NPM to build the Storybook server')
.option(
'--package-manager <npm|pnpm|yarn1|yarn2>',
'Force package manager for installing dependencies'
)
.option('-N --use-npm', 'Use NPM to install dependencies (deprecated)')
.option('-y --yes', 'Skip prompting the user')
.option('-n --dry-run', 'Only check for upgrades, do not install')
.option('-p --prerelease', 'Upgrade to the pre-release packages')
.option('-s --skip-check', 'Skip postinstall version and automigration checks')
.action((options) => upgrade(options));
.action((options: UpgradeOptions) => upgrade(options));

program
.command('info')
Expand Down Expand Up @@ -177,6 +187,8 @@ program
.description('Check storybook for known problems or migrations and apply fixes')
.option('-y --yes', 'Skip prompting the user')
.option('-n --dry-run', 'Only check for fixes, do not actually run them')
.option('--package-manager <npm|pnpm|yarn1|yarn2>', 'Force package manager')
.option('-N --use-npm', 'Use npm as package manager (deprecated)')
.action((fixId, options) =>
automigrate({ fixId, ...options }).catch((e) => {
logger.error(e);
Expand Down
3 changes: 2 additions & 1 deletion code/lib/cli/src/generators/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NpmOptions } from '../NpmOptions';
import { SupportedLanguage, Builder, ProjectType } from '../project_types';
import { JsPackageManager } from '../js-package-manager/JsPackageManager';
import { JsPackageManager, type PackageManagerName } from '../js-package-manager/JsPackageManager';

export type GeneratorOptions = {
language: SupportedLanguage;
Expand Down Expand Up @@ -31,6 +31,7 @@ export type Generator = (
) => Promise<void>;

export type CommandOptions = {
packageManager: PackageManagerName;
useNpm?: boolean;
usePnp?: boolean;
type?: ProjectType;
Expand Down
12 changes: 8 additions & 4 deletions code/lib/cli/src/initiate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import preactGenerator from './generators/PREACT';
import svelteGenerator from './generators/SVELTE';
import raxGenerator from './generators/RAX';
import serverGenerator from './generators/SERVER';
import { JsPackageManagerFactory, JsPackageManager } from './js-package-manager';
import { JsPackageManagerFactory, JsPackageManager, useNpmWarning } from './js-package-manager';
import { NpmOptions } from './NpmOptions';
import { automigrate } from './automigrate';
import { CommandOptions } from './generators/types';
Expand Down Expand Up @@ -220,7 +220,7 @@ const installStorybook = (
};

const projectTypeInquirer = async (
options: { yes?: boolean },
options: CommandOptions & { yes?: boolean },
packageManager: JsPackageManager
) => {
const manualAnswer = options.yes
Expand Down Expand Up @@ -251,7 +251,11 @@ const projectTypeInquirer = async (
};

export async function initiate(options: CommandOptions, pkg: Package): Promise<void> {
const packageManager = JsPackageManagerFactory.getPackageManager(options.useNpm);
const { useNpm, packageManager: pkgMgr } = options;
if (useNpm) {
useNpmWarning();
}
const packageManager = JsPackageManagerFactory.getPackageManager({ useNpm, force: pkgMgr });
const welcomeMessage = 'storybook init - the simplest way to add a Storybook to your project.';
logger.log(chalk.inverse(`\n ${welcomeMessage} \n`));

Expand Down Expand Up @@ -307,7 +311,7 @@ export async function initiate(options: CommandOptions, pkg: Package): Promise<v
packageManager.installDependencies();
}

await automigrate({ yes: options.yes || process.env.CI === 'true' });
await automigrate({ yes: options.yes || process.env.CI === 'true', useNpm, force: pkgMgr });

logger.log('\nTo run your Storybook, type:\n');
codeLog([packageManager.getRunStorybookCommand()]);
Expand Down
4 changes: 3 additions & 1 deletion code/lib/cli/src/js-package-manager/JsPackageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import storybookPackagesVersions from '../versions';

const logger = console;

export type PackageManagerName = 'npm' | 'yarn1' | 'yarn2' | 'pnpm';

/**
* Extract package name and version from input
*
Expand All @@ -31,7 +33,7 @@ interface JsPackageManagerOptions {
cwd?: string;
}
export abstract class JsPackageManager {
public abstract readonly type: 'npm' | 'yarn1' | 'yarn2';
public abstract readonly type: PackageManagerName;

public abstract initPackageJson(): void;

Expand Down
Loading

0 comments on commit 27f6985

Please sign in to comment.