164 lines
4.8 KiB
TypeScript
164 lines
4.8 KiB
TypeScript
import { joinPathFragments, logger } from '@nrwl/devkit';
|
|
import { findNodes } from 'nx/src/utils/typescript';
|
|
import 'dotenv/config';
|
|
import { existsSync, readFileSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { gte } from 'semver';
|
|
import ts = require('typescript');
|
|
import { CommonNxStorybookConfig, UiFramework } from '../utils/models';
|
|
import { CLIOptions } from '@storybook/types';
|
|
|
|
export interface NodePackage {
|
|
name: string;
|
|
version: string;
|
|
}
|
|
|
|
// TODO(katerina): Remove when Storybook 7
|
|
export function getStorybookFrameworkPath(uiFramework: UiFramework) {
|
|
const serverOptionsPaths = {
|
|
'@storybook/react': '@storybook/react/dist/cjs/server/options',
|
|
'@storybook/html': '@storybook/html/dist/cjs/server/options',
|
|
'@storybook/vue': '@storybook/vue/dist/cjs/server/options',
|
|
'@storybook/vue3': '@storybook/vue3/dist/cjs/server/options',
|
|
'@storybook/web-components':
|
|
'@storybook/web-components/dist/cjs/server/options',
|
|
'@storybook/svelte': '@storybook/svelte/dist/cjs/server/options',
|
|
};
|
|
|
|
if (isStorybookV62onwards(uiFramework)) {
|
|
return serverOptionsPaths[uiFramework];
|
|
} else {
|
|
return `${uiFramework}/dist/server/options`;
|
|
}
|
|
}
|
|
|
|
// TODO(katerina): Remove when Storybook 7
|
|
function isStorybookV62onwards(uiFramework: string) {
|
|
const storybookPackageVersion = require(join(
|
|
uiFramework,
|
|
'package.json'
|
|
)).version;
|
|
|
|
return gte(storybookPackageVersion, '6.2.0-rc.4');
|
|
}
|
|
|
|
// TODO(katerina): Remove when Storybook 7
|
|
export function runStorybookSetupCheck(
|
|
options: CLIOptions & CommonNxStorybookConfig
|
|
) {
|
|
webpackFinalPropertyCheck(options);
|
|
reactWebpack5Check(options);
|
|
}
|
|
|
|
// TODO(katerina): Remove when Storybook 7
|
|
function reactWebpack5Check(options: CLIOptions & CommonNxStorybookConfig) {
|
|
if (options.uiFramework === '@storybook/react') {
|
|
const source = mainJsTsFileContent(options.configDir);
|
|
const rootSource = mainJsTsFileContent('.storybook');
|
|
// check whether the current Storybook configuration has the webpack 5 builder enabled
|
|
if (
|
|
builderIsWebpackButNotWebpack5(source) &&
|
|
builderIsWebpackButNotWebpack5(rootSource)
|
|
) {
|
|
logger.warn(`
|
|
It looks like you use Webpack 5 but your Storybook setup is not configured to leverage that
|
|
and thus falls back to Webpack 4.
|
|
Make sure you upgrade your Storybook config to use Webpack 5.
|
|
|
|
- https://gist.github.com/shilman/8856ea1786dcd247139b47b270912324#upgrade
|
|
|
|
`);
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO(katerina): Remove when Storybook 7
|
|
function mainJsTsFileContent(configFolder: string): ts.SourceFile {
|
|
let storybookConfigFilePath = joinPathFragments(configFolder, 'main.js');
|
|
|
|
if (!existsSync(storybookConfigFilePath)) {
|
|
storybookConfigFilePath = joinPathFragments(configFolder, 'main.ts');
|
|
}
|
|
|
|
if (!existsSync(storybookConfigFilePath)) {
|
|
// looks like there's no main config file, so skip
|
|
return;
|
|
}
|
|
|
|
const storybookConfig = readFileSync(storybookConfigFilePath, {
|
|
encoding: 'utf8',
|
|
});
|
|
|
|
return ts.createSourceFile(
|
|
storybookConfigFilePath,
|
|
storybookConfig,
|
|
ts.ScriptTarget.Latest,
|
|
true
|
|
);
|
|
}
|
|
|
|
// TODO(katerina): Remove when Storybook 7
|
|
function webpackFinalPropertyCheck(
|
|
options: CLIOptions & CommonNxStorybookConfig
|
|
) {
|
|
let placesToCheck = [
|
|
{
|
|
path: joinPathFragments('.storybook', 'webpack.config.js'),
|
|
result: false,
|
|
},
|
|
{
|
|
path: joinPathFragments(options.configDir, 'webpack.config.js'),
|
|
result: false,
|
|
},
|
|
];
|
|
|
|
placesToCheck = placesToCheck
|
|
.map((entry) => {
|
|
return {
|
|
...entry,
|
|
result: existsSync(entry.path),
|
|
};
|
|
})
|
|
.filter((x) => x.result === true);
|
|
|
|
if (placesToCheck.length > 0) {
|
|
logger.warn(
|
|
`
|
|
You have a webpack.config.js files in your Storybook configuration:
|
|
${placesToCheck.map((x) => `- "${x.path}"`).join('\n ')}
|
|
|
|
Consider switching to the "webpackFinal" property declared in "main.js" (or "main.ts") instead.
|
|
${
|
|
options.uiFramework === '@storybook/react'
|
|
? 'https://nx.dev/storybook/migrate-webpack-final-react'
|
|
: 'https://nx.dev/storybook/migrate-webpack-final-angular'
|
|
}
|
|
`
|
|
);
|
|
}
|
|
}
|
|
|
|
// TODO(katerina): Remove when Storybook 7
|
|
export function builderIsWebpackButNotWebpack5(
|
|
storybookConfig: ts.SourceFile
|
|
): boolean {
|
|
const importArray = findNodes(storybookConfig, [
|
|
ts.SyntaxKind.PropertyAssignment,
|
|
]);
|
|
let builderIsWebpackNot5 = false;
|
|
importArray.forEach((parent) => {
|
|
const identifier = findNodes(parent, ts.SyntaxKind.Identifier);
|
|
const sbBuilder = findNodes(parent, ts.SyntaxKind.StringLiteral);
|
|
const builderText = sbBuilder?.[0]?.getText() ?? '';
|
|
if (
|
|
identifier?.[0]?.getText() === 'builder' &&
|
|
builderText.includes('webpack') &&
|
|
!builderText.includes('webpack5')
|
|
) {
|
|
builderIsWebpackNot5 = true;
|
|
}
|
|
});
|
|
|
|
return builderIsWebpackNot5;
|
|
}
|