From d703eb08805e55e1e7eb6f32f1c965a4e562b6ff Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 11 May 2023 15:36:58 +0200 Subject: [PATCH 1/6] add babel config file if needed as part of init --- code/lib/cli/src/babel-config.ts | 82 +++++++++++++------ .../cli/src/generators/REACT_SCRIPTS/index.ts | 2 +- code/lib/cli/src/generators/baseGenerator.ts | 53 ++++++++---- code/lib/cli/src/generators/types.ts | 2 +- code/lib/cli/src/helpers.ts | 1 + 5 files changed, 96 insertions(+), 44 deletions(-) diff --git a/code/lib/cli/src/babel-config.ts b/code/lib/cli/src/babel-config.ts index e97b51f0328d..24ea3436927b 100644 --- a/code/lib/cli/src/babel-config.ts +++ b/code/lib/cli/src/babel-config.ts @@ -9,6 +9,55 @@ export const generateStorybookBabelConfigInCWD = async () => { const target = process.cwd(); return generateStorybookBabelConfig({ target }); }; + +export const getBabelPresets = ({ typescript, jsx }: { typescript: boolean; jsx: boolean }) => { + const dependencies = ['@babel/preset-env']; + + if (typescript) { + dependencies.push('@babel/preset-typescript'); + } + + if (jsx) { + dependencies.push('@babel/preset-react'); + } + + return dependencies; +}; + +export const writeBabelConfigFile = async ({ + location, + typescript, + jsx, +}: { + location?: string; + typescript: boolean; + jsx: boolean; +}) => { + const fileLocation = location || path.join(process.cwd(), '.babelrc.json'); + + const presets: (string | [string, any])[] = [['@babel/preset-env', { targets: { chrome: 100 } }]]; + + if (typescript) { + presets.push('@babel/preset-typescript'); + } + + if (jsx) { + presets.push('@babel/preset-react'); + } + + const contents = JSON.stringify( + { + sourceType: 'unambiguous', + presets, + plugins: [], + }, + null, + 2 + ); + + await writeFile(fileLocation, contents); +}; + export const generateStorybookBabelConfig = async ({ target }: { target: string }) => { logger.info(`Generating the storybook default babel config at ${target}`); @@ -52,37 +101,16 @@ export const generateStorybookBabelConfig = async ({ target }: { target: string }, ]); - const added = ['@babel/preset-env']; - const presets: (string | [string, any])[] = [['@babel/preset-env', { targets: { chrome: 100 } }]]; - - if (typescript) { - added.push('@babel/preset-typescript'); - presets.push('@babel/preset-typescript'); - } - - if (jsx) { - added.push('@babel/preset-react'); - presets.push('@babel/preset-react'); - } - - const contents = JSON.stringify( - { - sourceType: 'unambiguous', - presets, - plugins: [], - }, - null, - 2 - ); + const dependencies = getBabelPresets({ typescript, jsx }); logger.info(`Writing file to ${location}`); - await writeFile(location, contents); + await writeBabelConfigFile({ location, typescript, jsx }); const { runInstall } = await prompts({ type: 'confirm', initial: true, name: 'runInstall', - message: `Shall we install the required dependencies now? (${added.join(', ')})`, + message: `Shall we install the required dependencies now? (${dependencies.join(', ')})`, }); if (runInstall) { @@ -90,10 +118,12 @@ export const generateStorybookBabelConfig = async ({ target }: { target: string const packageManager = JsPackageManagerFactory.getPackageManager(); - await packageManager.addDependencies({ installAsDevDependencies: true }, added); + await packageManager.addDependencies({ installAsDevDependencies: true }, dependencies); } else { logger.info( - `⚠️ Please remember to install the required dependencies yourself: (${added.join(', ')})` + `⚠️ Please remember to install the required dependencies yourself: (${dependencies.join( + ', ' + )})` ); } }; diff --git a/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts b/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts index 1871a13faedb..bda620f3548b 100644 --- a/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts +++ b/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts @@ -54,7 +54,7 @@ const generator: Generator = async (packageManager, npmOptions, options) => { extraAddons, extraPackages, staticDir: fs.existsSync(path.resolve('./public')) ? 'public' : undefined, - addBabel: false, + skipBabel: true, addESLint: true, extraMain, }); diff --git a/code/lib/cli/src/generators/baseGenerator.ts b/code/lib/cli/src/generators/baseGenerator.ts index 9a44785b7146..278bc316c906 100644 --- a/code/lib/cli/src/generators/baseGenerator.ts +++ b/code/lib/cli/src/generators/baseGenerator.ts @@ -3,12 +3,12 @@ import fse from 'fs-extra'; import { dedent } from 'ts-dedent'; import type { NpmOptions } from '../NpmOptions'; import type { SupportedRenderers, SupportedFrameworks, Builder } from '../project_types'; -import { externalFrameworks, CoreBuilder } from '../project_types'; -import { getBabelDependencies, copyTemplateFiles } from '../helpers'; +import { SupportedLanguage, externalFrameworks, CoreBuilder } from '../project_types'; +import { copyTemplateFiles } from '../helpers'; import { configureMain, configurePreview } from './configure'; import type { JsPackageManager } from '../js-package-manager'; import { getPackageDetails } from '../js-package-manager'; -import { generateStorybookBabelConfigInCWD } from '../babel-config'; +import { getBabelPresets, writeBabelConfigFile } from '../babel-config'; import packageVersions from '../versions'; import type { FrameworkOptions, GeneratorOptions } from './types'; @@ -19,7 +19,7 @@ const defaultOptions: FrameworkOptions = { addScripts: true, addMainFile: true, addComponents: true, - addBabel: false, + skipBabel: false, addESLint: false, extraMain: undefined, framework: undefined, @@ -154,7 +154,7 @@ export async function baseGenerator( addScripts, addMainFile, addComponents, - addBabel, + skipBabel, addESLint, extraMain, extensions, @@ -260,18 +260,39 @@ export async function baseGenerator( await configurePreview({ frameworkPreviewParts, storybookConfigFolder, language, rendererId }); - const babelDependencies = - addBabel && builder !== CoreBuilder.Vite - ? await getBabelDependencies(packageManager, packageJson) - : []; - const isNewFolder = !files.some( - (fname) => fname.startsWith('.babel') || fname.startsWith('babel') || fname === 'package.json' - ); - if (isNewFolder) { - await generateStorybookBabelConfigInCWD(); - } + const depsToInstall = [...versionedPackages]; + + // Add basic babel config for a select few frameworks that need it, if they do not have a babel config file already + if (builder !== CoreBuilder.Vite && !skipBabel) { + const frameworksThatNeedBabelConfig = [ + '@storybook/react-webpack5', + '@storybook/vue-webpack5', + '@storybook/vue3-webpack5', + '@storybook/html-webpack5', + '@storybook/web-components-webpack5', + ]; + const needsBabelConfig = frameworkPackages.find((pkg) => + frameworksThatNeedBabelConfig.includes(pkg) + ); + const hasNoBabelFile = !files.some( + (fname) => fname.startsWith('.babel') || fname.startsWith('babel') + ); - const depsToInstall = [...versionedPackages, ...babelDependencies]; + if (hasNoBabelFile && needsBabelConfig) { + const isTypescript = language !== SupportedLanguage.JAVASCRIPT; + const isReact = rendererId === 'react'; + depsToInstall.push( + ...getBabelPresets({ + typescript: isTypescript, + jsx: isReact, + }) + ); + await writeBabelConfigFile({ + typescript: isTypescript, + jsx: isReact, + }); + } + } if (depsToInstall.length > 0) { await packageManager.addDependencies({ ...npmOptions, packageJson }, depsToInstall); diff --git a/code/lib/cli/src/generators/types.ts b/code/lib/cli/src/generators/types.ts index bb62010bbd58..4ae347bd4d49 100644 --- a/code/lib/cli/src/generators/types.ts +++ b/code/lib/cli/src/generators/types.ts @@ -18,7 +18,7 @@ export interface FrameworkOptions { addScripts?: boolean; addMainFile?: boolean; addComponents?: boolean; - addBabel?: boolean; + skipBabel?: boolean; addESLint?: boolean; extraMain?: any; extensions?: string[]; diff --git a/code/lib/cli/src/helpers.ts b/code/lib/cli/src/helpers.ts index b8cd29253ebd..a1e162a3d263 100644 --- a/code/lib/cli/src/helpers.ts +++ b/code/lib/cli/src/helpers.ts @@ -119,6 +119,7 @@ export function codeLog(codeLines: string[], leftPadAmount?: number) { /** * Detect if any babel dependencies need to be added to the project + * This is currently used by react-native generator * @param {Object} packageJson The current package.json so we can inspect its contents * @returns {Array} Contains the packages and versions that need to be installed * @example From b51bd98c2dea8a016f0f39b10a347acb392da5bc Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 11 May 2023 20:24:45 +0200 Subject: [PATCH 2/6] Suggest ESLint plugin as part of Storybook init --- .../automigrate/fixes/eslint-plugin.test.ts | 1 + .../src/automigrate/fixes/eslint-plugin.ts | 37 ++------ .../src/automigrate/helpers/eslintPlugin.ts | 95 +++++++++++++++++++ .../src/automigrate/helpers/getEslintInfo.ts | 20 ---- .../cli/src/generators/REACT_SCRIPTS/index.ts | 1 - code/lib/cli/src/generators/baseGenerator.ts | 30 ++++-- code/lib/cli/src/generators/types.ts | 1 - .../js-package-manager/JsPackageManager.ts | 19 ---- 8 files changed, 128 insertions(+), 76 deletions(-) create mode 100644 code/lib/cli/src/automigrate/helpers/eslintPlugin.ts delete mode 100644 code/lib/cli/src/automigrate/helpers/getEslintInfo.ts diff --git a/code/lib/cli/src/automigrate/fixes/eslint-plugin.test.ts b/code/lib/cli/src/automigrate/fixes/eslint-plugin.test.ts index 78fdedec90b8..cb242c9b0626 100644 --- a/code/lib/cli/src/automigrate/fixes/eslint-plugin.test.ts +++ b/code/lib/cli/src/automigrate/fixes/eslint-plugin.test.ts @@ -52,6 +52,7 @@ describe('eslint-plugin fix', () => { await expect( checkEslint({ packageJson, + hasEslint: false, }) ).resolves.toBeFalsy(); }); diff --git a/code/lib/cli/src/automigrate/fixes/eslint-plugin.ts b/code/lib/cli/src/automigrate/fixes/eslint-plugin.ts index 9b461e97d1a7..a34f30e78340 100644 --- a/code/lib/cli/src/automigrate/fixes/eslint-plugin.ts +++ b/code/lib/cli/src/automigrate/fixes/eslint-plugin.ts @@ -1,10 +1,12 @@ import chalk from 'chalk'; import { dedent } from 'ts-dedent'; -import { readConfig, writeConfig } from '@storybook/csf-tools'; -import { readFile, readJson, writeJson } from 'fs-extra'; -import detectIndent from 'detect-indent'; -import { findEslintFile, SUPPORTED_ESLINT_EXTENSIONS } from '../helpers/getEslintInfo'; +import { + configureEslintPlugin, + extractEslintInfo, + findEslintFile, + SUPPORTED_ESLINT_EXTENSIONS, +} from '../helpers/eslintPlugin'; import type { Fix } from '../types'; @@ -25,12 +27,9 @@ export const eslintPlugin: Fix = { id: 'eslintPlugin', async check({ packageManager }) { - const allDependencies = await packageManager.getAllDependencies(); + const { hasEslint, isStorybookPluginInstalled } = await extractEslintInfo(packageManager); - const eslintPluginStorybook = allDependencies['eslint-plugin-storybook']; - const eslintDependency = allDependencies.eslint; - - if (eslintPluginStorybook || !eslintDependency) { + if (isStorybookPluginInstalled || !hasEslint) { return null; } @@ -82,26 +81,8 @@ export const eslintPlugin: Fix = { return; } - logger.info(`✅ Adding Storybook plugin to ${eslintFile}`); if (!dryRun) { - if (eslintFile.endsWith('json')) { - const eslintConfig = (await readJson(eslintFile)) as { extends?: string[] }; - const existingConfigValue = Array.isArray(eslintConfig.extends) - ? eslintConfig.extends - : [eslintConfig.extends]; - eslintConfig.extends = [...(existingConfigValue || []), 'plugin:storybook/recommended']; - - const eslintFileContents = await readFile(eslintFile, 'utf8'); - const spaces = detectIndent(eslintFileContents).amount || 2; - await writeJson(eslintFile, eslintConfig, { spaces }); - } else { - const eslint = await readConfig(eslintFile); - const extendsConfig = eslint.getFieldValue(['extends']) || []; - const existingConfigValue = Array.isArray(extendsConfig) ? extendsConfig : [extendsConfig]; - eslint.setFieldValue(['extends'], [...existingConfigValue, 'plugin:storybook/recommended']); - - await writeConfig(eslint); - } + await configureEslintPlugin(eslintFile, packageManager); } }, }; diff --git a/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts b/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts new file mode 100644 index 000000000000..3d11b1774077 --- /dev/null +++ b/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts @@ -0,0 +1,95 @@ +import fse, { readFile, readJson, writeJson } from 'fs-extra'; + +import { dedent } from 'ts-dedent'; +import detectIndent from 'detect-indent'; +import { readConfig, writeConfig } from '@storybook/csf-tools'; +import prompts from 'prompts'; +import chalk from 'chalk'; +import type { JsPackageManager } from '../../js-package-manager'; +import { paddedLog } from '../../helpers'; + +export const SUPPORTED_ESLINT_EXTENSIONS = ['js', 'cjs', 'json']; +const UNSUPPORTED_ESLINT_EXTENSIONS = ['yaml', 'yml']; + +export const findEslintFile = () => { + const filePrefix = '.eslintrc'; + const unsupportedExtension = UNSUPPORTED_ESLINT_EXTENSIONS.find((ext: string) => + fse.existsSync(`${filePrefix}.${ext}`) + ); + + if (unsupportedExtension) { + throw new Error(unsupportedExtension); + } + + const extension = SUPPORTED_ESLINT_EXTENSIONS.find((ext: string) => + fse.existsSync(`${filePrefix}.${ext}`) + ); + return extension ? `${filePrefix}.${extension}` : null; +}; + +export async function extractEslintInfo(packageManager: JsPackageManager) { + const allDependencies = await packageManager.getAllDependencies(); + const packageJson = await packageManager.retrievePackageJson(); + let eslintConfigFile; + + try { + eslintConfigFile = findEslintFile(); + } catch (err) { + // + } + + const isStorybookPluginInstalled = !!allDependencies['eslint-plugin-storybook']; + const hasEslint = allDependencies.eslint || eslintConfigFile || packageJson.eslintConfig; + return { hasEslint, isStorybookPluginInstalled, eslintConfigFile }; +} + +export async function configureEslintPlugin(eslintFile: string, packageManager: JsPackageManager) { + if (eslintFile) { + paddedLog(`Configuring Storybook ESLint plugin at ${eslintFile}`); + if (eslintFile.endsWith('json')) { + const eslintConfig = (await readJson(eslintFile)) as { extends?: string[] }; + const existingConfigValue = Array.isArray(eslintConfig.extends) + ? eslintConfig.extends + : [eslintConfig.extends]; + eslintConfig.extends = [...(existingConfigValue || []), 'plugin:storybook/recommended']; + + const eslintFileContents = await readFile(eslintFile, 'utf8'); + const spaces = detectIndent(eslintFileContents).amount || 2; + await writeJson(eslintFile, eslintConfig, { spaces }); + } else { + const eslint = await readConfig(eslintFile); + const extendsConfig = eslint.getFieldValue(['extends']) || []; + const existingConfigValue = Array.isArray(extendsConfig) ? extendsConfig : [extendsConfig]; + eslint.setFieldValue(['extends'], [...existingConfigValue, 'plugin:storybook/recommended']); + + await writeConfig(eslint); + } + } else { + paddedLog(`Configuring eslint-plugin-storybook in your package.json`); + const packageJson = await packageManager.retrievePackageJson(); + await packageManager.writePackageJson({ + ...packageJson, + eslintConfig: { + ...packageJson.eslintConfig, + extends: [...(packageJson.eslintConfig?.extends || []), 'plugin:storybook/recommended'], + }, + }); + } +} + +export const suggestESLintPlugin = async (): Promise => { + const { shouldInstall } = await prompts({ + type: 'confirm', + name: 'shouldInstall', + message: dedent` + We detected that you're using ESLint. Storybook provides a plugin that gives the best experience with Storybook and helps follow best practices: ${chalk.yellow( + 'https://github.com/storybookjs/eslint-plugin-storybook#readme' + )} + + Would you like to install it? + `, + initial: true, + }); + + return shouldInstall; +}; diff --git a/code/lib/cli/src/automigrate/helpers/getEslintInfo.ts b/code/lib/cli/src/automigrate/helpers/getEslintInfo.ts deleted file mode 100644 index 698e2c4bde7e..000000000000 --- a/code/lib/cli/src/automigrate/helpers/getEslintInfo.ts +++ /dev/null @@ -1,20 +0,0 @@ -import fse from 'fs-extra'; - -export const SUPPORTED_ESLINT_EXTENSIONS = ['js', 'cjs', 'json']; -const UNSUPPORTED_ESLINT_EXTENSIONS = ['yaml', 'yml']; - -export const findEslintFile = () => { - const filePrefix = '.eslintrc'; - const unsupportedExtension = UNSUPPORTED_ESLINT_EXTENSIONS.find((ext: string) => - fse.existsSync(`${filePrefix}.${ext}`) - ); - - if (unsupportedExtension) { - throw new Error(unsupportedExtension); - } - - const extension = SUPPORTED_ESLINT_EXTENSIONS.find((ext: string) => - fse.existsSync(`${filePrefix}.${ext}`) - ); - return extension ? `${filePrefix}.${extension}` : null; -}; diff --git a/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts b/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts index bda620f3548b..8948aea95500 100644 --- a/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts +++ b/code/lib/cli/src/generators/REACT_SCRIPTS/index.ts @@ -55,7 +55,6 @@ const generator: Generator = async (packageManager, npmOptions, options) => { extraPackages, staticDir: fs.existsSync(path.resolve('./public')) ? 'public' : undefined, skipBabel: true, - addESLint: true, extraMain, }); }; diff --git a/code/lib/cli/src/generators/baseGenerator.ts b/code/lib/cli/src/generators/baseGenerator.ts index 278bc316c906..b2ffc0815ef5 100644 --- a/code/lib/cli/src/generators/baseGenerator.ts +++ b/code/lib/cli/src/generators/baseGenerator.ts @@ -4,13 +4,18 @@ import { dedent } from 'ts-dedent'; import type { NpmOptions } from '../NpmOptions'; import type { SupportedRenderers, SupportedFrameworks, Builder } from '../project_types'; import { SupportedLanguage, externalFrameworks, CoreBuilder } from '../project_types'; -import { copyTemplateFiles } from '../helpers'; +import { copyTemplateFiles, paddedLog } from '../helpers'; import { configureMain, configurePreview } from './configure'; import type { JsPackageManager } from '../js-package-manager'; import { getPackageDetails } from '../js-package-manager'; import { getBabelPresets, writeBabelConfigFile } from '../babel-config'; import packageVersions from '../versions'; import type { FrameworkOptions, GeneratorOptions } from './types'; +import { + configureEslintPlugin, + extractEslintInfo, + suggestESLintPlugin, +} from '../automigrate/helpers/eslintPlugin'; const defaultOptions: FrameworkOptions = { extraPackages: [], @@ -20,7 +25,6 @@ const defaultOptions: FrameworkOptions = { addMainFile: true, addComponents: true, skipBabel: false, - addESLint: false, extraMain: undefined, framework: undefined, extensions: undefined, @@ -155,7 +159,6 @@ export async function baseGenerator( addMainFile, addComponents, skipBabel, - addESLint, extraMain, extensions, storybookConfigFolder, @@ -294,7 +297,24 @@ export async function baseGenerator( } } + try { + const { hasEslint, isStorybookPluginInstalled, eslintConfigFile } = await extractEslintInfo( + packageManager + ); + + if (hasEslint && !isStorybookPluginInstalled) { + const shouldInstallESLintPlugin = await suggestESLintPlugin(); + if (shouldInstallESLintPlugin) { + depsToInstall.push('eslint-plugin-storybook'); + await configureEslintPlugin(eslintConfigFile, packageManager); + } + } + } catch (err) { + // any failure regarding configuring the eslint plugin should not fail the whole generator + } + if (depsToInstall.length > 0) { + paddedLog('Installing Storybook dependencies'); await packageManager.addDependencies({ ...npmOptions, packageJson }, depsToInstall); } @@ -304,10 +324,6 @@ export async function baseGenerator( }); } - if (addESLint) { - await packageManager.addESLintConfig(); - } - if (addComponents) { const templateLocation = hasFrameworkTemplates(framework) ? framework : rendererId; await copyTemplateFiles({ diff --git a/code/lib/cli/src/generators/types.ts b/code/lib/cli/src/generators/types.ts index 4ae347bd4d49..6ef446c6538c 100644 --- a/code/lib/cli/src/generators/types.ts +++ b/code/lib/cli/src/generators/types.ts @@ -19,7 +19,6 @@ export interface FrameworkOptions { addMainFile?: boolean; addComponents?: boolean; skipBabel?: boolean; - addESLint?: boolean; extraMain?: any; extensions?: string[]; framework?: Record; diff --git a/code/lib/cli/src/js-package-manager/JsPackageManager.ts b/code/lib/cli/src/js-package-manager/JsPackageManager.ts index 8e8ae0b2ce1c..f2d1c1b3ed3d 100644 --- a/code/lib/cli/src/js-package-manager/JsPackageManager.ts +++ b/code/lib/cli/src/js-package-manager/JsPackageManager.ts @@ -365,25 +365,6 @@ export abstract class JsPackageManager { }); } - public async addESLintConfig() { - const packageJson = await this.retrievePackageJson(); - await this.writePackageJson({ - ...packageJson, - eslintConfig: { - ...packageJson.eslintConfig, - overrides: [ - ...(packageJson.eslintConfig?.overrides || []), - { - files: ['**/*.stories.*'], - rules: { - 'import/no-anonymous-default-export': 'off', - }, - }, - ], - }, - }); - } - public async addScripts(scripts: Record) { const packageJson = await this.retrievePackageJson(); await this.writePackageJson({ From 31344f8aded7afc626c0ca77429944dd898513bc Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 12 May 2023 08:37:06 +0200 Subject: [PATCH 3/6] only suggest ESLint plugin in non-CI environments --- code/lib/cli/src/generators/baseGenerator.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/code/lib/cli/src/generators/baseGenerator.ts b/code/lib/cli/src/generators/baseGenerator.ts index b2ffc0815ef5..5f94d6d969bc 100644 --- a/code/lib/cli/src/generators/baseGenerator.ts +++ b/code/lib/cli/src/generators/baseGenerator.ts @@ -298,15 +298,17 @@ export async function baseGenerator( } try { - const { hasEslint, isStorybookPluginInstalled, eslintConfigFile } = await extractEslintInfo( - packageManager - ); + if (process.env.CI !== 'true') { + const { hasEslint, isStorybookPluginInstalled, eslintConfigFile } = await extractEslintInfo( + packageManager + ); - if (hasEslint && !isStorybookPluginInstalled) { - const shouldInstallESLintPlugin = await suggestESLintPlugin(); - if (shouldInstallESLintPlugin) { - depsToInstall.push('eslint-plugin-storybook'); - await configureEslintPlugin(eslintConfigFile, packageManager); + if (hasEslint && !isStorybookPluginInstalled) { + const shouldInstallESLintPlugin = await suggestESLintPlugin(); + if (shouldInstallESLintPlugin) { + depsToInstall.push('eslint-plugin-storybook'); + await configureEslintPlugin(eslintConfigFile, packageManager); + } } } } catch (err) { From 4eb040130602ce9b68b1224fddb991ac10bda811 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 12 May 2023 09:47:03 +0200 Subject: [PATCH 4/6] remove prompt from babelrc command --- .../src/automigrate/fixes/missing-babelrc.ts | 11 +++---- code/lib/cli/src/babel-config.ts | 33 +++---------------- 2 files changed, 10 insertions(+), 34 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/missing-babelrc.ts b/code/lib/cli/src/automigrate/fixes/missing-babelrc.ts index 2e13685fd8b4..1b403a6b0d4b 100644 --- a/code/lib/cli/src/automigrate/fixes/missing-babelrc.ts +++ b/code/lib/cli/src/automigrate/fixes/missing-babelrc.ts @@ -65,20 +65,19 @@ export const missingBabelRc: Fix = { If your project does not have a babel configuration file, we can generate one that's equivalent to the 6.x defaults for you. Keep in mind that this can affect your project if it uses babel, and you may need to make additional changes based on your projects needs. + We can create a ${chalk.blue( + '.babelrc.json' + )} file with some basic configuration and add any necessary package devDependencies. + ${chalk.bold( 'Note:' - )} This automatic setup doesn't work in a monorepo, see the babel documentation for how to setup babel manually: + )} After installing the necessary presets, if it does not work in a monorepo, see the babel documentation for reference: ${chalk.yellow('https://babeljs.io/docs')} - We can create a ${chalk.blue( - '.babelrc.json' - )} file with some basic configuration and add any necessary package devDependencies. - Please see the migration guide for more information: ${chalk.yellow( 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#babel-mode-v7-exclusively' )} - `; }, async run() { diff --git a/code/lib/cli/src/babel-config.ts b/code/lib/cli/src/babel-config.ts index 24ea3436927b..c918ba78cff7 100644 --- a/code/lib/cli/src/babel-config.ts +++ b/code/lib/cli/src/babel-config.ts @@ -2,7 +2,6 @@ import { writeFile, pathExists } from 'fs-extra'; import { logger } from '@storybook/node-logger'; import path from 'path'; import prompts from 'prompts'; -import chalk from 'chalk'; import { JsPackageManagerFactory } from './js-package-manager'; export const generateStorybookBabelConfigInCWD = async () => { @@ -59,7 +58,7 @@ export const writeBabelConfigFile = async ({ }; export const generateStorybookBabelConfig = async ({ target }: { target: string }) => { - logger.info(`Generating the storybook default babel config at ${target}`); + logger.info(`Generating the Storybook default babel config at ${target}`); const fileName = '.babelrc.json'; const location = path.join(target, fileName); @@ -80,12 +79,6 @@ export const generateStorybookBabelConfig = async ({ target }: { target: string } } - logger.info( - `The config will contain ${chalk.yellow( - '@babel/preset-env' - )} and you will be prompted for additional presets, if you wish to add them depending on your project needs.` - ); - const { typescript, jsx } = await prompts([ { type: 'confirm', @@ -106,24 +99,8 @@ export const generateStorybookBabelConfig = async ({ target }: { target: string logger.info(`Writing file to ${location}`); await writeBabelConfigFile({ location, typescript, jsx }); - const { runInstall } = await prompts({ - type: 'confirm', - initial: true, - name: 'runInstall', - message: `Shall we install the required dependencies now? (${dependencies.join(', ')})`, - }); - - if (runInstall) { - logger.info(`Installing dependencies...`); - - const packageManager = JsPackageManagerFactory.getPackageManager(); - - await packageManager.addDependencies({ installAsDevDependencies: true }, dependencies); - } else { - logger.info( - `⚠️ Please remember to install the required dependencies yourself: (${dependencies.join( - ', ' - )})` - ); - } + const packageManager = JsPackageManagerFactory.getPackageManager(); + + logger.info(`Installing dependencies (${dependencies.join(', ')})`); + await packageManager.addDependencies({ installAsDevDependencies: true }, dependencies); }; From a2cb39bcbaa00220313bb0b1edf39108a76c4ff9 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 12 May 2023 15:49:40 +0200 Subject: [PATCH 5/6] Update code/lib/cli/src/automigrate/helpers/eslintPlugin.ts Co-authored-by: Valentin Palkovic --- code/lib/cli/src/automigrate/helpers/eslintPlugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts b/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts index 3d11b1774077..91170bf10bed 100644 --- a/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts +++ b/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts @@ -82,7 +82,7 @@ export const suggestESLintPlugin = async (): Promise => { type: 'confirm', name: 'shouldInstall', message: dedent` - We detected that you're using ESLint. Storybook provides a plugin that gives the best experience with Storybook and helps follow best practices: ${chalk.yellow( + We have detected that you're using ESLint. Storybook provides a plugin that gives the best experience with Storybook and helps follow best practices: ${chalk.yellow( 'https://github.com/storybookjs/eslint-plugin-storybook#readme' )} From fe187b6d9187d2d825298e32a7d7e873e6983dc5 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 12 May 2023 15:54:04 +0200 Subject: [PATCH 6/6] improve types --- code/lib/cli/src/automigrate/helpers/eslintPlugin.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts b/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts index 91170bf10bed..3d31d1111498 100644 --- a/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts +++ b/code/lib/cli/src/automigrate/helpers/eslintPlugin.ts @@ -27,10 +27,14 @@ export const findEslintFile = () => { return extension ? `${filePrefix}.${extension}` : null; }; -export async function extractEslintInfo(packageManager: JsPackageManager) { +export async function extractEslintInfo(packageManager: JsPackageManager): Promise<{ + hasEslint: boolean; + isStorybookPluginInstalled: boolean; + eslintConfigFile: string | null; +}> { const allDependencies = await packageManager.getAllDependencies(); const packageJson = await packageManager.retrievePackageJson(); - let eslintConfigFile; + let eslintConfigFile: string | null = null; try { eslintConfigFile = findEslintFile();