add missing-babelrc automigration

This commit is contained in:
Yann Braga 2022-12-20 12:51:17 +01:00
parent 5f23fc59c6
commit 834c796011
3 changed files with 184 additions and 0 deletions

View File

@ -17,6 +17,7 @@ import { autodocsTrue } from './autodocs-true';
import { sveltekitFramework } from './sveltekit-framework';
import { addReact } from './add-react';
import { nodeJsRequirement } from './nodejs-requirement';
import { missingBabelRc } from './missing-babelrc';
export * from '../types';
@ -38,4 +39,5 @@ export const fixes: Fix[] = [
mdx1to2,
autodocsTrue,
addReact,
missingBabelRc,
];

View File

@ -0,0 +1,91 @@
/* eslint-disable no-underscore-dangle */
/// <reference types="@types/jest" />;
import path from 'path';
import type { JsPackageManager } from '../../js-package-manager';
import { missingBabelRc } from './missing-babelrc';
// eslint-disable-next-line global-require, jest/no-mocks-import
jest.mock('fs-extra', () => require('../../../../../__mocks__/fs-extra'));
const babelContent = JSON.stringify({
sourceType: 'unambiguous',
presets: [
[
'@babel/preset-env',
{
targets: {
chrome: 100,
},
},
],
'@babel/preset-typescript',
'@babel/preset-react',
],
plugins: [],
});
const check = async ({ packageJson = {}, main = {}, extraFiles }: any) => {
if (extraFiles) {
// eslint-disable-next-line global-require
require('fs-extra').__setMockFiles({
[path.join('.storybook', 'main.js')]: `module.exports = ${JSON.stringify(main)};`,
...extraFiles,
});
}
const packageManager = {
retrievePackageJson: () => ({ dependencies: {}, devDependencies: {}, ...packageJson }),
} as JsPackageManager;
return missingBabelRc.check({ packageManager });
};
describe('missing-babelrc fix', () => {
it('skips when babelrc config is present', async () => {
const packageJson = {
devDependencies: {
'@storybook/react': '^7.0.0',
'@storybook/react-webpack5': '^7.0.0',
},
};
// different babel extensions
await expect(
check({ extraFiles: { '.babelrc': babelContent }, packageJson })
).resolves.toBeNull();
await expect(
check({ extraFiles: { '.babelrc.json': babelContent }, packageJson })
).resolves.toBeNull();
await expect(
check({ extraFiles: { 'babel.config.json': babelContent }, packageJson })
).resolves.toBeNull();
// babel field in package.json
await expect(
check({ packageJson: { ...packageJson, babel: babelContent } })
).resolves.toBeNull();
});
it('skips when using a framework that provides babel config', async () => {
const packageJson = {
devDependencies: {
'@storybook/react': '^7.0.0',
'@storybook/nextjs': '^7.0.0',
},
};
await expect(check({ packageJson })).resolves.toBeNull();
});
it('prompts when babelrc file is missing and framework does not provide babel config', async () => {
const packageJson = {
devDependencies: {
'@storybook/react': '^7.0.0',
'@storybook/react-webpack5': '^7.0.0',
},
};
await expect(check({ packageJson })).resolves.toBe({
needsBabelRc: true,
});
});
});

View File

@ -0,0 +1,91 @@
import chalk from 'chalk';
import dedent from 'ts-dedent';
import semver from 'semver';
import { getStorybookInfo } from '@storybook/core-common';
import { loadPartialConfigAsync } from '@babel/core';
import { readConfig } from '@storybook/csf-tools';
import type { Fix } from '../types';
interface MissingBabelRcOptions {
needsBabelRc: boolean;
}
const logger = console;
const frameworksThatNeedBabelConfig = [
'@storybook/angular',
'@storybook/react-webpack5',
'@storybook/vue-webpack5',
'@storybook/vue3-webpack5',
'@storybook/preact-webpack5',
'@storybook/html-webpack5',
'@storybook/react-vite',
'@storybook/vue-vite',
'@storybook/vue3-vite',
'@storybook/preact-vite',
'@storybook/html-vite',
];
export const missingBabelRc: Fix<MissingBabelRcOptions> = {
id: 'missing-babelrc',
promptOnly: true,
async check({ packageManager }) {
const packageJson = packageManager.retrievePackageJson();
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?
`);
}
if (!semver.gte(storybookCoerced, '7.0.0')) {
return null;
}
if (!mainConfig) {
logger.warn('Unable to find storybook main.js config, skipping');
return null;
}
const main = await readConfig(mainConfig);
const frameworkField = main.getFieldValue(['framework']);
const frameworkPackage =
typeof frameworkField === 'string' ? frameworkField : frameworkField?.name;
if (frameworksThatNeedBabelConfig.includes(frameworkPackage)) {
const config = await loadPartialConfigAsync();
if (!config.config && !packageJson.babel) {
return { needsBabelRc: true };
}
}
return null;
},
prompt() {
return dedent`
${chalk.bold(
chalk.red('Attention')
)}: We could not automatically make this change. You'll need to do it manually.
Storybook now uses Babel mode v7 exclusively. In 6.x, Storybook provided its own babel settings out of the box. Now, Storybook's uses your project's babel settings (.babelrc, babel.config.js, etc.) instead.
In the new mode, Storybook expects you to provide a configuration file. If you want a configuration file that's equivalent to the 6.x default, you can run the following command in your project directory:
${chalk.blue('npx sb@next babelrc')}
This will create a ${chalk.blue(
'.babelrc.json'
)} file with some basic configuration and add new package devDependencies accordingly.
Please see the migration guide for more information:
${chalk.yellow(
'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#babel-mode-v7-exclusively'
)}
`;
},
};