diff --git a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts index 461a36aec648..ea8b55d4973c 100644 --- a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts +++ b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts @@ -165,7 +165,7 @@ export default async ( inject: false, template, templateParameters: { - version: packageJson.version, + version: packageJson?.version, globals: { CONFIG_TYPE: configType, LOGLEVEL: logLevel, diff --git a/code/core/src/core-server/build-dev.ts b/code/core/src/core-server/build-dev.ts index fc07aa11ab95..5c87a7d9ccd8 100644 --- a/code/core/src/core-server/build-dev.ts +++ b/code/core/src/core-server/build-dev.ts @@ -1,6 +1,7 @@ import { join, relative, resolve } from 'node:path'; import { + getConfigInfo, getProjectRoot, loadAllPresets, loadMainConfig, @@ -8,6 +9,7 @@ import { resolvePathInStorybookCache, serverResolve, validateFrameworkName, + versions, } from '@storybook/core/common'; import { oneWayHash, telemetry } from '@storybook/core/telemetry'; import type { BuilderOptions, CLIOptions, LoadOptions, Options } from '@storybook/core/types'; @@ -32,18 +34,33 @@ import { warnOnIncompatibleAddons } from './utils/warnOnIncompatibleAddons'; import { warnWhenUsingArgTypesRegex } from './utils/warnWhenUsingArgTypesRegex'; export async function buildDevStandalone( - options: CLIOptions & LoadOptions & BuilderOptions + options: CLIOptions & + LoadOptions & + BuilderOptions & { + storybookVersion?: string; + previewConfigPath?: string; + } ): Promise<{ port: number; address: string; networkAddress: string }> { const { packageJson, versionUpdates } = options; - invariant( - packageJson.version !== undefined, - `Expected package.json#version to be defined in the "${packageJson.name}" package}` - ); + let { storybookVersion, previewConfigPath } = options; + const configDir = resolve(options.configDir); + if (packageJson) { + invariant( + packageJson.version !== undefined, + `Expected package.json#version to be defined in the "${packageJson.name}" package}` + ); + storybookVersion = packageJson.version; + previewConfigPath = getConfigInfo(packageJson, configDir).previewConfig ?? undefined; + } else { + if (!storybookVersion) { + storybookVersion = versions.storybook; + } + } // updateInfo are cached, so this is typically pretty fast const [port, versionCheck] = await Promise.all([ getServerPort(options.port, { exactPort: options.exactPort }), versionUpdates - ? updateCheck(packageJson.version) + ? updateCheck(storybookVersion) : Promise.resolve({ success: false, cached: false, data: {}, time: Date.now() }), ]); @@ -60,7 +77,6 @@ export async function buildDevStandalone( } const rootDir = getProjectRoot(); - const configDir = resolve(options.configDir); const cacheKey = oneWayHash(relative(rootDir, configDir)); const cacheOutputDir = resolvePathInStorybookCache('public', cacheKey); @@ -92,13 +108,13 @@ export async function buildDevStandalone( frameworkName = frameworkName || 'custom'; try { - await warnOnIncompatibleAddons(packageJson.version); + await warnOnIncompatibleAddons(storybookVersion); } catch (e) { console.warn('Storybook failed to check addon compatibility', e); } try { - await warnWhenUsingArgTypesRegex(packageJson, configDir, config); + await warnWhenUsingArgTypesRegex(previewConfigPath, config); } catch (e) {} // Load first pass: We need to determine the builder @@ -224,7 +240,7 @@ export async function buildDevStandalone( if (!options.quiet) { outputStartupInformation({ updateInfo: versionCheck, - version: packageJson.version, + version: storybookVersion, name, address, networkAddress, diff --git a/code/core/src/core-server/presets/common-preset.ts b/code/core/src/core-server/presets/common-preset.ts index 506ceb55ea2a..bca9a1c9cfe6 100644 --- a/code/core/src/core-server/presets/common-preset.ts +++ b/code/core/src/core-server/presets/common-preset.ts @@ -141,7 +141,7 @@ export const babel = async (_: unknown, options: Options) => { }; export const title = (previous: string, options: Options) => - previous || options.packageJson.name || false; + previous || options.packageJson?.name || false; export const logLevel = (previous: any, options: Options) => previous || options.loglevel || 'info'; diff --git a/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts b/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts index b36755fcd6ab..207e762ede60 100644 --- a/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts +++ b/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts @@ -1,5 +1,4 @@ -import { getConfigInfo } from '@storybook/core/common'; -import type { PackageJson, StorybookConfig } from '@storybook/core/types'; +import type { StorybookConfig } from '@storybook/core/types'; import { babelParse } from '@storybook/core/csf-tools'; @@ -10,12 +9,10 @@ import { readFile } from 'fs-extra'; import { dedent } from 'ts-dedent'; export async function warnWhenUsingArgTypesRegex( - packageJson: PackageJson, - configDir: string, + previewConfigPath: string | undefined, config: StorybookConfig ) { - const { previewConfig } = getConfigInfo(packageJson, configDir); - const previewContent = previewConfig ? await readFile(previewConfig, 'utf8') : ''; + const previewContent = previewConfigPath ? await readFile(previewConfigPath, 'utf8') : ''; const hasVisualTestAddon = config?.addons?.some((it) => @@ -24,10 +21,10 @@ export async function warnWhenUsingArgTypesRegex( : it.name === '@chromatic-com/storybook' ) ?? false; - if (hasVisualTestAddon && previewConfig && previewContent.includes('argTypesRegex')) { + if (hasVisualTestAddon && previewConfigPath && previewContent.includes('argTypesRegex')) { // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606 const file: BabelFile = new babel.File( - { filename: previewConfig }, + { filename: previewConfigPath }, { code: previewContent, ast: babelParse(previewContent) } ); @@ -39,7 +36,7 @@ export async function warnWhenUsingArgTypesRegex( 'actions.argTypesRegex' )} together with the visual test addon: - ${path.buildCodeFrameError(previewConfig).message} + ${path.buildCodeFrameError(previewConfigPath).message} We recommend removing the ${chalk.cyan( 'argTypesRegex' diff --git a/code/core/src/types/modules/core-common.ts b/code/core/src/types/modules/core-common.ts index fb2f8542d514..8e71a4cadb2a 100644 --- a/code/core/src/types/modules/core-common.ts +++ b/code/core/src/types/modules/core-common.ts @@ -151,7 +151,7 @@ export type PackageJson = PackageJsonFromTypeFest & Record; // TODO: This could be exported to the outside world and used in `options.ts` file of each `@storybook/APP` // like it's described in docs/api/new-frameworks.md export interface LoadOptions { - packageJson: PackageJson; + packageJson?: PackageJson; outputDir?: string; configDir?: string; cacheKey?: string; diff --git a/code/presets/create-react-app/src/helpers/processCraConfig.ts b/code/presets/create-react-app/src/helpers/processCraConfig.ts index befe78f217b7..eeb28fe91b2e 100644 --- a/code/presets/create-react-app/src/helpers/processCraConfig.ts +++ b/code/presets/create-react-app/src/helpers/processCraConfig.ts @@ -39,7 +39,7 @@ export const processCraConfig = async ( * * See: https://github.com/storybookjs/storybook/pull/9157 */ - const storybookVersion = semver.coerce(options.packageJson.version) || ''; + const storybookVersion = semver.coerce(options.packageJson?.version) || ''; const isStorybook530 = semver.gte(storybookVersion, '5.3.0'); const babelOptions = await options.presets.apply('babel');