From 1f27f574720fd48701f91a0745904776ae09c314 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Mon, 20 Feb 2023 18:19:14 +0100 Subject: [PATCH] refactor all webpack5 related migrations --- .../src/automigrate/fixes/angular12.test.ts | 48 ++++++----- .../cli/src/automigrate/fixes/angular12.ts | 12 ++- .../cli/src/automigrate/fixes/cra5.test.ts | 35 ++++---- code/lib/cli/src/automigrate/fixes/cra5.ts | 16 ++-- .../cli/src/automigrate/fixes/vue3.test.ts | 40 ++++++---- code/lib/cli/src/automigrate/fixes/vue3.ts | 12 ++- .../src/automigrate/fixes/webpack5.test.ts | 39 +++++---- .../lib/cli/src/automigrate/fixes/webpack5.ts | 80 ++++--------------- .../helpers/checkWebpack5Builder.ts | 46 +++++++++++ 9 files changed, 159 insertions(+), 169 deletions(-) create mode 100644 code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts diff --git a/code/lib/cli/src/automigrate/fixes/angular12.test.ts b/code/lib/cli/src/automigrate/fixes/angular12.test.ts index 02da0ae88506..f0aaaf774b0a 100644 --- a/code/lib/cli/src/automigrate/fixes/angular12.test.ts +++ b/code/lib/cli/src/automigrate/fixes/angular12.test.ts @@ -1,46 +1,44 @@ -/* eslint-disable no-underscore-dangle */ -import * as path from 'path'; import type { StorybookConfig } from '@storybook/types'; -import type { JsPackageManager, PackageJson } from '../../js-package-manager'; +import type { PackageJson } from '../../js-package-manager'; +import { makePackageManager, mockStorybookData } from '../helpers/testing-helpers'; import { angular12 } from './angular12'; -// eslint-disable-next-line global-require, jest/no-mocks-import -jest.mock('fs-extra', () => require('../../../../../__mocks__/fs-extra')); - const checkAngular12 = async ({ packageJson, - main, + main: mainConfig = {}, + storybookVersion = '7.0.0', }: { packageJson: PackageJson; - main: Partial; + main?: Partial & Record; + storybookVersion?: string; }) => { - // eslint-disable-next-line global-require - require('fs-extra').__setMockFiles({ - [path.join('.storybook', 'main.js')]: `module.exports = ${JSON.stringify(main)};`, + mockStorybookData({ mainConfig, storybookVersion }); + + return angular12.check({ + packageManager: makePackageManager(packageJson), + configDir: '', }); - const packageManager = { - retrievePackageJson: () => ({ dependencies: {}, devDependencies: {}, ...packageJson }), - } as JsPackageManager; - return angular12.check({ packageManager }); }; describe('angular12 fix', () => { + afterEach(jest.restoreAllMocks); + describe('sb < 6.3', () => { describe('angular12 dependency', () => { const packageJson = { - dependencies: { '@storybook/react': '^6.2.0', '@angular/core': '^12.0.0' }, + dependencies: { '@storybook/angular': '^6.2.0', '@angular/core': '^12.0.0' }, }; it('should fail', async () => { await expect( checkAngular12({ packageJson, - main: {}, + storybookVersion: '6.2.0', }) ).rejects.toThrow(); }); }); describe('no angular dependency', () => { - const packageJson = { dependencies: { '@storybook/react': '^6.2.0' } }; + const packageJson = { dependencies: { '@storybook/angular': '^6.2.0' } }; it('should no-op', async () => { await expect( checkAngular12({ @@ -54,7 +52,7 @@ describe('angular12 fix', () => { describe('sb 6.3 - 7.0', () => { describe('angular12 dependency', () => { const packageJson = { - dependencies: { '@storybook/react': '^6.3.0', '@angular/core': '^12.0.0' }, + dependencies: { '@storybook/angular': '^6.3.0', '@angular/core': '^12.0.0' }, }; describe('webpack5 builder', () => { it('should no-op', async () => { @@ -62,6 +60,7 @@ describe('angular12 fix', () => { checkAngular12({ packageJson, main: { core: { builder: 'webpack5' } }, + storybookVersion: '6.3.0', }) ).resolves.toBeFalsy(); }); @@ -82,10 +81,11 @@ describe('angular12 fix', () => { checkAngular12({ packageJson, main: { core: { builder: 'webpack4' } }, + storybookVersion: '6.3.0', }) ).resolves.toMatchObject({ angularVersion: '^12.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); @@ -94,11 +94,11 @@ describe('angular12 fix', () => { await expect( checkAngular12({ packageJson, - main: {}, + storybookVersion: '6.3.0', }) ).resolves.toMatchObject({ angularVersion: '^12.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); @@ -108,7 +108,6 @@ describe('angular12 fix', () => { await expect( checkAngular12({ packageJson: {}, - main: {}, }) ).resolves.toBeFalsy(); }); @@ -117,13 +116,12 @@ describe('angular12 fix', () => { describe('sb 7.0+', () => { describe('angular12 dependency', () => { const packageJson = { - dependencies: { '@storybook/react': '^7.0.0-alpha.0', '@angular/core': '^12.0.0' }, + dependencies: { '@storybook/angular': '^7.0.0-alpha.0', '@angular/core': '^12.0.0' }, }; it('should no-op', async () => { await expect( checkAngular12({ packageJson, - main: {}, }) ).resolves.toBeFalsy(); }); diff --git a/code/lib/cli/src/automigrate/fixes/angular12.ts b/code/lib/cli/src/automigrate/fixes/angular12.ts index b22a3e131a56..a778556e9207 100644 --- a/code/lib/cli/src/automigrate/fixes/angular12.ts +++ b/code/lib/cli/src/automigrate/fixes/angular12.ts @@ -1,15 +1,14 @@ import chalk from 'chalk'; import { dedent } from 'ts-dedent'; import semver from 'semver'; -import type { ConfigFile } from '@storybook/csf-tools'; import type { Fix } from '../types'; import { webpack5 } from './webpack5'; +import { checkWebpack5Builder } from '../helpers/checkWebpack5Builder'; interface Angular12RunOptions { angularVersion: string; // FIXME angularPresetVersion: string; storybookVersion: string; - main: ConfigFile; } /** @@ -21,17 +20,16 @@ interface Angular12RunOptions { export const angular12: Fix = { id: 'angular12', - async check({ packageManager }) { - const packageJson = packageManager.retrievePackageJson(); - const { dependencies, devDependencies } = packageJson; - const angularVersion = dependencies['@angular/core'] || devDependencies['@angular/core']; + async check({ packageManager, configDir }) { + const allDependencies = packageManager.getAllDependencies(); + const angularVersion = allDependencies['@angular/core']; const angularCoerced = semver.coerce(angularVersion)?.version; if (!angularCoerced || semver.lt(angularCoerced, '12.0.0')) { return null; } - const builderInfo = await webpack5.checkWebpack5Builder(packageJson); + const builderInfo = await checkWebpack5Builder({ packageManager, configDir }); return builderInfo ? { angularVersion, ...builderInfo } : null; }, diff --git a/code/lib/cli/src/automigrate/fixes/cra5.test.ts b/code/lib/cli/src/automigrate/fixes/cra5.test.ts index db3066f6f5a8..58caadb19065 100644 --- a/code/lib/cli/src/automigrate/fixes/cra5.test.ts +++ b/code/lib/cli/src/automigrate/fixes/cra5.test.ts @@ -1,30 +1,27 @@ -/* eslint-disable no-underscore-dangle */ -import * as path from 'path'; import type { StorybookConfig } from '@storybook/types'; -import type { JsPackageManager, PackageJson } from '../../js-package-manager'; +import type { PackageJson } from '../../js-package-manager'; import { cra5 } from './cra5'; - -// eslint-disable-next-line global-require, jest/no-mocks-import -jest.mock('fs-extra', () => require('../../../../../__mocks__/fs-extra')); +import { makePackageManager, mockStorybookData } from '../helpers/testing-helpers'; const checkCra5 = async ({ packageJson, - main, + main: mainConfig, + storybookVersion = '7.0.0', }: { packageJson: PackageJson; - main: Partial; + main?: Partial & Record; + storybookVersion?: string; }) => { - // eslint-disable-next-line global-require - require('fs-extra').__setMockFiles({ - [path.join('.storybook', 'main.js')]: `module.exports = ${JSON.stringify(main)};`, + mockStorybookData({ mainConfig, storybookVersion }); + + return cra5.check({ + packageManager: makePackageManager(packageJson), }); - const packageManager = { - retrievePackageJson: () => ({ dependencies: {}, devDependencies: {}, ...packageJson }), - } as JsPackageManager; - return cra5.check({ packageManager }); }; describe('cra5 fix', () => { + afterEach(jest.restoreAllMocks); + describe('sb < 6.3', () => { describe('cra5 dependency', () => { const packageJson = { @@ -34,7 +31,7 @@ describe('cra5 fix', () => { await expect( checkCra5({ packageJson, - main: {}, + storybookVersion: '6.2.0', }) ).rejects.toThrow(); }); @@ -82,10 +79,11 @@ describe('cra5 fix', () => { checkCra5({ packageJson, main: { core: { builder: 'webpack4' } }, + storybookVersion: '6.3.0', }) ).resolves.toMatchObject({ craVersion: '^5.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); @@ -95,10 +93,11 @@ describe('cra5 fix', () => { checkCra5({ packageJson, main: {}, + storybookVersion: '6.3.0', }) ).resolves.toMatchObject({ craVersion: '^5.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); diff --git a/code/lib/cli/src/automigrate/fixes/cra5.ts b/code/lib/cli/src/automigrate/fixes/cra5.ts index b4d9e156e83a..04ca458d6871 100644 --- a/code/lib/cli/src/automigrate/fixes/cra5.ts +++ b/code/lib/cli/src/automigrate/fixes/cra5.ts @@ -1,15 +1,14 @@ import chalk from 'chalk'; import { dedent } from 'ts-dedent'; import semver from 'semver'; -import type { ConfigFile } from '@storybook/csf-tools'; import type { Fix } from '../types'; import { webpack5 } from './webpack5'; +import { checkWebpack5Builder } from '../helpers/checkWebpack5Builder'; interface CRA5RunOptions { craVersion: string; // FIXME craPresetVersion: string; storybookVersion: string; - main: ConfigFile; } /** @@ -21,25 +20,22 @@ interface CRA5RunOptions { export const cra5: Fix = { id: 'cra5', - async check({ packageManager }) { - const packageJson = packageManager.retrievePackageJson(); - const { dependencies, devDependencies } = packageJson; - const craVersion = dependencies['react-scripts'] || devDependencies['react-scripts']; + async check({ packageManager, configDir }) { + const allDependencies = packageManager.getAllDependencies(); + const craVersion = allDependencies['react-scripts']; const craCoerced = semver.coerce(craVersion)?.version; if (!craCoerced || semver.lt(craCoerced, '5.0.0')) { return null; } - const builderInfo = await webpack5.checkWebpack5Builder(packageJson); + const builderInfo = await checkWebpack5Builder({ configDir, packageManager }); return builderInfo ? { craVersion, ...builderInfo } : null; }, - prompt({ craVersion, ...rest }) { + prompt({ craVersion }) { const craFormatted = chalk.cyan(`Create React App (CRA) ${craVersion}`); - console.log({ ...rest }); - return dedent` We've detected you are running ${craFormatted} which is powered by webpack5. Your Storybook's main.js files specifies webpack4, which is incompatible. diff --git a/code/lib/cli/src/automigrate/fixes/vue3.test.ts b/code/lib/cli/src/automigrate/fixes/vue3.test.ts index 6ca7a23eef61..a4effab1ea23 100644 --- a/code/lib/cli/src/automigrate/fixes/vue3.test.ts +++ b/code/lib/cli/src/automigrate/fixes/vue3.test.ts @@ -1,23 +1,27 @@ -/* eslint-disable no-underscore-dangle */ -import * as path from 'path'; -import type { JsPackageManager, PackageJson } from '../../js-package-manager'; +import type { StorybookConfig } from '@storybook/types'; +import type { PackageJson } from '../../js-package-manager'; import { vue3 } from './vue3'; +import { makePackageManager, mockStorybookData } from '../helpers/testing-helpers'; -// eslint-disable-next-line global-require, jest/no-mocks-import -jest.mock('fs-extra', () => require('../../../../../__mocks__/fs-extra')); +const checkVue3 = async ({ + packageJson, + main: mainConfig = {}, + storybookVersion = '7.0.0', +}: { + packageJson: PackageJson; + main?: Partial & Record; + storybookVersion?: string; +}) => { + mockStorybookData({ mainConfig, storybookVersion }); -const checkVue3 = async ({ packageJson, main }: { packageJson: PackageJson; main: unknown }) => { - // eslint-disable-next-line global-require - require('fs-extra').__setMockFiles({ - [path.join('.storybook', 'main.js')]: `module.exports = ${JSON.stringify(main)};`, + return vue3.check({ + packageManager: makePackageManager(packageJson), }); - const packageManager = { - retrievePackageJson: () => ({ dependencies: {}, devDependencies: {}, ...packageJson }), - } as JsPackageManager; - return vue3.check({ packageManager }); }; describe('vue3 fix', () => { + afterEach(jest.restoreAllMocks); + describe('sb < 6.3', () => { describe('vue3 dependency', () => { const packageJson = { @@ -27,7 +31,7 @@ describe('vue3 fix', () => { await expect( checkVue3({ packageJson, - main: {}, + storybookVersion: '6.2.0', }) ).rejects.toThrow(); }); @@ -38,7 +42,7 @@ describe('vue3 fix', () => { await expect( checkVue3({ packageJson, - main: {}, + storybookVersion: '6.2.0', }) ).resolves.toBeFalsy(); }); @@ -75,10 +79,11 @@ describe('vue3 fix', () => { checkVue3({ packageJson, main: { core: { builder: 'webpack4' } }, + storybookVersion: '6.3.0', }) ).resolves.toMatchObject({ vueVersion: '^3.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); @@ -88,10 +93,11 @@ describe('vue3 fix', () => { checkVue3({ packageJson, main: {}, + storybookVersion: '6.3.0', }) ).resolves.toMatchObject({ vueVersion: '^3.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); diff --git a/code/lib/cli/src/automigrate/fixes/vue3.ts b/code/lib/cli/src/automigrate/fixes/vue3.ts index de38ed472123..f1c5041e1885 100644 --- a/code/lib/cli/src/automigrate/fixes/vue3.ts +++ b/code/lib/cli/src/automigrate/fixes/vue3.ts @@ -1,14 +1,13 @@ import chalk from 'chalk'; import { dedent } from 'ts-dedent'; import semver from 'semver'; -import type { ConfigFile } from '@storybook/csf-tools'; import type { Fix } from '../types'; import { webpack5 } from './webpack5'; +import { checkWebpack5Builder } from '../helpers/checkWebpack5Builder'; interface Vue3RunOptions { vueVersion: string; storybookVersion: string; - main: ConfigFile; } /** @@ -20,17 +19,16 @@ interface Vue3RunOptions { export const vue3: Fix = { id: 'vue3', - async check({ packageManager }) { - const packageJson = packageManager.retrievePackageJson(); - const { dependencies, devDependencies } = packageJson; - const vueVersion = dependencies.vue || devDependencies.vue; + async check({ configDir, packageManager }) { + const allDependencies = packageManager.getAllDependencies(); + const vueVersion = allDependencies.vue; const vueCoerced = semver.coerce(vueVersion)?.version; if (!vueCoerced || semver.lt(vueCoerced, '3.0.0')) { return null; } - const builderInfo = await webpack5.checkWebpack5Builder(packageJson); + const builderInfo = await checkWebpack5Builder({ configDir, packageManager }); return builderInfo ? { vueVersion, ...builderInfo } : null; }, diff --git a/code/lib/cli/src/automigrate/fixes/webpack5.test.ts b/code/lib/cli/src/automigrate/fixes/webpack5.test.ts index c231fa477e4c..2da36108d95d 100644 --- a/code/lib/cli/src/automigrate/fixes/webpack5.test.ts +++ b/code/lib/cli/src/automigrate/fixes/webpack5.test.ts @@ -1,30 +1,28 @@ -/* eslint-disable no-underscore-dangle */ -import * as path from 'path'; import type { StorybookConfig } from '@storybook/types'; -import type { JsPackageManager, PackageJson } from '../../js-package-manager'; +import type { PackageJson } from '../../js-package-manager'; import { webpack5 } from './webpack5'; - -// eslint-disable-next-line global-require, jest/no-mocks-import -jest.mock('fs-extra', () => require('../../../../../__mocks__/fs-extra')); +import { makePackageManager, mockStorybookData } from '../helpers/testing-helpers'; const checkWebpack5 = async ({ packageJson, - main, + main: mainConfig, + storybookVersion = '6.3.0', }: { packageJson: PackageJson; - main: Partial; + main?: Partial & Record; + storybookVersion?: string; }) => { - // eslint-disable-next-line global-require - require('fs-extra').__setMockFiles({ - [path.join('.storybook', 'main.js')]: `module.exports = ${JSON.stringify(main)};`, + mockStorybookData({ mainConfig, storybookVersion }); + + return webpack5.check({ + packageManager: makePackageManager(packageJson), + configDir: '', }); - const packageManager = { - retrievePackageJson: () => ({ dependencies: {}, devDependencies: {}, ...packageJson }), - } as JsPackageManager; - return webpack5.check({ packageManager }); }; describe('webpack5 fix', () => { + afterEach(jest.restoreAllMocks); + describe('sb < 6.3', () => { describe('webpack5 dependency', () => { const packageJson = { dependencies: { '@storybook/react': '^6.2.0', webpack: '^5.0.0' } }; @@ -32,7 +30,7 @@ describe('webpack5 fix', () => { await expect( checkWebpack5({ packageJson, - main: {}, + storybookVersion: '6.2.0', }) ).rejects.toThrow(); }); @@ -43,7 +41,7 @@ describe('webpack5 fix', () => { await expect( checkWebpack5({ packageJson, - main: {}, + storybookVersion: '6.2.0', }) ).resolves.toBeFalsy(); }); @@ -81,7 +79,7 @@ describe('webpack5 fix', () => { }) ).resolves.toMatchObject({ webpackVersion: '^5.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); @@ -94,7 +92,7 @@ describe('webpack5 fix', () => { }) ).resolves.toMatchObject({ webpackVersion: '^5.0.0', - storybookVersion: '^6.3.0', + storybookVersion: '6.3.0', }); }); }); @@ -104,7 +102,6 @@ describe('webpack5 fix', () => { await expect( checkWebpack5({ packageJson: {}, - main: {}, }) ).resolves.toBeFalsy(); }); @@ -118,7 +115,6 @@ describe('webpack5 fix', () => { webpack: '4', }, }, - main: {}, }) ).resolves.toBeFalsy(); }); @@ -134,6 +130,7 @@ describe('webpack5 fix', () => { checkWebpack5({ packageJson, main: {}, + storybookVersion: '7.0.0', }) ).resolves.toBeFalsy(); }); diff --git a/code/lib/cli/src/automigrate/fixes/webpack5.ts b/code/lib/cli/src/automigrate/fixes/webpack5.ts index 68bf103fdad0..edac5e468696 100644 --- a/code/lib/cli/src/automigrate/fixes/webpack5.ts +++ b/code/lib/cli/src/automigrate/fixes/webpack5.ts @@ -1,24 +1,15 @@ import chalk from 'chalk'; import { dedent } from 'ts-dedent'; import semver from 'semver'; -import type { ConfigFile } from '@storybook/csf-tools'; -import { readConfig, writeConfig } from '@storybook/csf-tools'; -import { getStorybookInfo } from '@storybook/core-common'; import type { Fix } from '../types'; -import type { PackageJsonWithDepsAndDevDeps } from '../../js-package-manager'; +import { checkWebpack5Builder } from '../helpers/checkWebpack5Builder'; +import { updateMainConfig } from '../helpers/mainConfigFile'; const logger = console; interface Webpack5RunOptions { webpackVersion: string; storybookVersion: string; - main: ConfigFile; -} - -interface CheckBuilder { - checkWebpack5Builder: ( - packageJson: PackageJsonWithDepsAndDevDeps - ) => Promise<{ storybookVersion: string; main: ConfigFile }>; } /** @@ -31,58 +22,13 @@ interface CheckBuilder { * - Add core.builder = 'webpack5' to main.js * - Add 'webpack5' as a project dependency */ -export const webpack5: Fix & CheckBuilder = { +export const webpack5: Fix = { id: 'webpack5', - async checkWebpack5Builder(packageJson: PackageJsonWithDepsAndDevDeps) { - const { mainConfig, version: storybookVersion } = getStorybookInfo(packageJson); - - const storybookCoerced = storybookVersion && semver.coerce(storybookVersion)?.version; - if (!storybookCoerced) { - throw new Error(dedent` - ❌ Unable to determine storybook version. - 🤔 Are you running automigrate from your project directory? Please specify your Storybook config directory with the --config-dir flag. - `); - } - - if (semver.lt(storybookCoerced, '6.3.0')) { - logger.warn( - dedent` - Detected SB 6.3 or below, please upgrade storybook to use webpack5. - - To upgrade to the latest stable release, run this from your project directory: - - ${chalk.cyan('npx storybook upgrade')} - - Add the ${chalk.cyan('--prerelease')} flag to get the latest prerelease. - `.trim() - ); - return null; - } - - if (semver.gte(storybookCoerced, '7.0.0')) { - return null; - } - - if (!mainConfig) { - logger.warn('Unable to find storybook main.js config'); - return null; - } - const main = await readConfig(mainConfig); - const builder = main.getFieldValue(['core', 'builder']); - if (builder && builder !== 'webpack4') { - logger.info(`Found builder ${builder}, skipping`); - return null; - } - - return { storybookVersion, main }; - }, - - async check({ packageManager }) { - const packageJson = packageManager.retrievePackageJson(); - const { dependencies, devDependencies } = packageJson; + async check({ configDir, packageManager }) { + const allDependencies = packageManager.retrievePackageJson().dependencies; - const webpackVersion = dependencies.webpack || devDependencies.webpack; + const webpackVersion = allDependencies.webpack; const webpackCoerced = semver.coerce(webpackVersion)?.version; if ( @@ -92,7 +38,7 @@ export const webpack5: Fix & CheckBuilder = { ) return null; - const builderInfo = await this.checkWebpack5Builder(packageJson); + const builderInfo = await checkWebpack5Builder({ configDir, packageManager }); return builderInfo ? { webpackVersion, ...builderInfo } : null; }, @@ -113,7 +59,12 @@ export const webpack5: Fix & CheckBuilder = { `; }, - async run({ result: { main, storybookVersion, webpackVersion }, packageManager, dryRun }) { + async run({ + result: { storybookVersion, webpackVersion }, + packageManager, + dryRun, + mainConfigPath, + }) { const deps = [`@storybook/builder-webpack5@${storybookVersion}`]; // this also gets called by 'cra5' fix so we need to add // webpack5 at the project root so that it gets hoisted @@ -125,8 +76,9 @@ export const webpack5: Fix & CheckBuilder = { logger.info('✅ Setting `core.builder` to `@storybook/builder-webpack5` in main.js'); if (!dryRun) { - main.setFieldValue(['core', 'builder'], '@storybook/builder-webpack5'); - await writeConfig(main); + await updateMainConfig({ mainConfigPath, dryRun }, async (main) => { + main.setFieldValue(['core', 'builder'], '@storybook/builder-webpack5'); + }); } }, }; diff --git a/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts b/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts new file mode 100644 index 000000000000..b900d40b89bd --- /dev/null +++ b/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts @@ -0,0 +1,46 @@ +import chalk from 'chalk'; +import semver from 'semver'; +import dedent from 'ts-dedent'; +import type { GetStorybookData } from './mainConfigFile'; +import { getStorybookData } from './mainConfigFile'; + +const logger = console; + +export const checkWebpack5Builder = async ({ + configDir, + packageManager, +}: Parameters[0]) => { + const { mainConfig, storybookVersion } = await getStorybookData({ configDir, packageManager }); + + if (semver.lt(storybookVersion, '6.3.0')) { + logger.warn( + dedent` + Detected SB 6.3 or below, please upgrade storybook to use webpack5. + + To upgrade to the latest stable release, run this from your project directory: + + ${chalk.cyan('npx storybook upgrade')} + + Add the ${chalk.cyan('--prerelease')} flag to get the latest prerelease. + `.trim() + ); + return null; + } + + if (semver.gte(storybookVersion, '7.0.0')) { + return null; + } + + if (!mainConfig) { + logger.warn('Unable to find storybook main.js config'); + return null; + } + + const builder = mainConfig.core?.builder; + if (builder && builder !== 'webpack4') { + logger.info(`Found builder ${builder}, skipping`); + return null; + } + + return { storybookVersion }; +};