diff --git a/code/presets/create-react-app/src/helpers/checkPresets.ts b/code/presets/create-react-app/src/helpers/checkPresets.ts index 38d11839343c..2827dab51f58 100644 --- a/code/presets/create-react-app/src/helpers/checkPresets.ts +++ b/code/presets/create-react-app/src/helpers/checkPresets.ts @@ -7,7 +7,7 @@ const incompatiblePresets = ['@storybook/preset-scss', '@storybook/preset-typesc export const checkPresets = (options: PluginOptions): void => { const { presetsList } = options; - presetsList.forEach((preset: string | { name: string }) => { + presetsList?.forEach((preset: string | { name: string }) => { const presetName = typeof preset === 'string' ? preset : preset.name; if (incompatiblePresets.includes(presetName)) { logger.warn( diff --git a/code/presets/create-react-app/src/helpers/mergePlugins.ts b/code/presets/create-react-app/src/helpers/mergePlugins.ts index 4c3ff84ead18..c5fc7888674e 100644 --- a/code/presets/create-react-app/src/helpers/mergePlugins.ts +++ b/code/presets/create-react-app/src/helpers/mergePlugins.ts @@ -1,18 +1,19 @@ -import type { Configuration } from 'webpack'; +import type { Configuration, WebpackPluginInstance } from 'webpack'; import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin'; -export const mergePlugins = (...args: Configuration['plugins']): Configuration['plugins'] => - args.reduce((plugins, plugin) => { +export const mergePlugins = (...args: WebpackPluginInstance[]): Configuration['plugins'] => + args?.reduce((plugins, plugin) => { if ( - plugins.some( - (includedPlugin) => includedPlugin.constructor.name === plugin.constructor.name + plugins?.some( + (includedPlugin: WebpackPluginInstance) => + includedPlugin?.constructor.name === plugin?.constructor.name ) || - plugin.constructor.name === 'WebpackManifestPlugin' + plugin?.constructor.name === 'WebpackManifestPlugin' ) { return plugins; } let updatedPlugin = plugin; - if (plugin.constructor.name === 'ReactRefreshPlugin') { + if (plugin?.constructor.name === 'ReactRefreshPlugin') { // Storybook uses webpack-hot-middleware // https://github.com/storybookjs/presets/issues/177 @@ -22,5 +23,5 @@ export const mergePlugins = (...args: Configuration['plugins']): Configuration[' }, }); } - return [...plugins, updatedPlugin]; - }, [] as Configuration['plugins']); + return [...(plugins ?? []), updatedPlugin]; + }, [] as WebpackPluginInstance[]); diff --git a/code/presets/create-react-app/src/helpers/processCraConfig.ts b/code/presets/create-react-app/src/helpers/processCraConfig.ts index 25024ada0351..734776b03d4c 100644 --- a/code/presets/create-react-app/src/helpers/processCraConfig.ts +++ b/code/presets/create-react-app/src/helpers/processCraConfig.ts @@ -38,8 +38,9 @@ export const processCraConfig = ( const storybookVersion = semver.coerce(options.packageJson.version) || ''; const isStorybook530 = semver.gte(storybookVersion, '5.3.0'); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return craWebpackConfig.module!.rules.reduce((rules, rule): RuleSetRule[] => { + if (!craWebpackConfig?.module?.rules) return []; + + return craWebpackConfig.module.rules.reduce((rules, rule): RuleSetRule[] => { const { oneOf, include } = rule as RuleSetRule; // Add our `configDir` to support JSX and TypeScript in that folder. @@ -61,6 +62,7 @@ export const processCraConfig = ( return [ ...rules, { + // @ts-expect-error (not type correct) oneOf: oneOf.map((oneOfRule: RuleSetRule): RuleSetRule => { if (oneOfRule.type === 'asset/resource') { if (isStorybook530) { diff --git a/code/presets/create-react-app/src/index.ts b/code/presets/create-react-app/src/index.ts index e480e438ef91..9d2de88293e1 100644 --- a/code/presets/create-react-app/src/index.ts +++ b/code/presets/create-react-app/src/index.ts @@ -1,6 +1,6 @@ /* eslint-disable import/no-extraneous-dependencies */ import { join, relative, dirname } from 'path'; -import type { Configuration, RuleSetRule } from 'webpack'; +import type { Configuration, RuleSetRule, WebpackPluginInstance } from 'webpack'; import semver from 'semver'; import { logger } from '@storybook/node-logger'; import PnpWebpackPlugin from 'pnp-webpack-plugin'; @@ -78,12 +78,13 @@ const webpack = async ( // Remove existing rules related to JavaScript and TypeScript. logger.info(`=> Removing existing JavaScript and TypeScript rules.`); - const filteredRules = - webpackConfig.module && - webpackConfig.module.rules.filter( - ({ test }: RuleSetRule) => - !(test instanceof RegExp && ((test && test.test('.js')) || test.test('.ts'))) - ); + const filteredRules = (webpackConfig.module?.rules as RuleSetRule[])?.filter((rule) => { + if (typeof rule === 'string') { + return false; + } + const { test } = rule; + return !(test instanceof RegExp && (test?.test('.js') || test?.test('.ts'))); + }); // Require the CRA config and set the appropriate mode. const craWebpackConfigPath = join(scriptsPath, 'config', 'webpack.config'); @@ -133,8 +134,8 @@ const webpack = async ( // NOTE: this prioritizes the storybook version of a plugin // when there are duplicates between SB and CRA plugins: mergePlugins( - ...(webpackConfig.plugins || []), - ...(craWebpackConfig.plugins ?? []), + ...((webpackConfig.plugins ?? []) as WebpackPluginInstance[]), + ...((craWebpackConfig.plugins ?? []) as WebpackPluginInstance[]), ...tsDocgenPlugin ), resolve: { diff --git a/code/presets/create-react-app/tsconfig.json b/code/presets/create-react-app/tsconfig.json index a7d41e8a79b5..a4429176e35f 100644 --- a/code/presets/create-react-app/tsconfig.json +++ b/code/presets/create-react-app/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "strict": false + "strict": true }, "include": ["src/**/*"] }