diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json index e58484eb8951..0ff1ac9090fe 100644 --- a/code/lib/core-common/package.json +++ b/code/lib/core-common/package.json @@ -44,6 +44,7 @@ }, "dependencies": { "@babel/core": "^7.20.2", + "@storybook/csf-tools": "7.0.0-beta.38", "@storybook/node-logger": "7.0.0-beta.38", "@storybook/types": "7.0.0-beta.38", "@types/babel__core": "^7.1.20", @@ -57,7 +58,7 @@ "file-system-cache": "^2.0.0", "find-up": "^5.0.0", "fs-extra": "^11.1.0", - "glob": "^7.1.6", + "glob-promise": "^4.2.0", "handlebars": "^4.7.7", "lazy-universal-dotenv": "^4.0.0", "picomatch": "^2.3.0", diff --git a/code/lib/core-common/src/utils/load-main-config.ts b/code/lib/core-common/src/utils/load-main-config.ts index 743a863a956a..c2168816d5fa 100644 --- a/code/lib/core-common/src/utils/load-main-config.ts +++ b/code/lib/core-common/src/utils/load-main-config.ts @@ -3,8 +3,12 @@ import type { StorybookConfig } from '@storybook/types'; import { serverRequire } from './interpret-require'; import { validateConfigurationFiles } from './validate-configuration-files'; -export function loadMainConfig({ configDir }: { configDir: string }): StorybookConfig { - validateConfigurationFiles(configDir); +export async function loadMainConfig({ + configDir, +}: { + configDir: string; +}): Promise { + await validateConfigurationFiles(configDir); return serverRequire(path.resolve(configDir, 'main')); } diff --git a/code/lib/core-common/src/utils/validate-configuration-files.ts b/code/lib/core-common/src/utils/validate-configuration-files.ts index 040a12b1191d..b66d9af3955a 100644 --- a/code/lib/core-common/src/utils/validate-configuration-files.ts +++ b/code/lib/core-common/src/utils/validate-configuration-files.ts @@ -1,20 +1,36 @@ import { dedent } from 'ts-dedent'; -import glob from 'glob'; +import { promise as glob } from 'glob-promise'; import path from 'path'; +import { readConfig } from '@storybook/csf-tools'; +import { once } from '@storybook/node-logger'; import { boost } from './interpret-files'; -export function validateConfigurationFiles(configDir: string) { +export async function validateConfigurationFiles(configDir: string) { const extensionsPattern = `{${Array.from(boost).join(',')}}`; - const exists = (file: string) => - !!glob.sync(path.resolve(configDir, `${file}${extensionsPattern}`)).length; + const mainConfigMatches = await glob(path.resolve(configDir, `main${extensionsPattern}`)); - const main = exists('main'); + const [mainConfigPath] = mainConfigMatches; - if (!main) { + if (mainConfigMatches.length > 1) { + once.warn(dedent` + Multiple main files found in your configDir (${path.resolve(configDir)}). + Storybook will use the first one found and ignore the others. Please remove the extra files. + `); + } + + if (!mainConfigPath) { throw new Error(dedent` No configuration files have been found in your configDir (${path.resolve(configDir)}). - Storybook needs either a "main" or "config" file. + Storybook needs "main.js" file, please add it. `); + } else { + const main = await readConfig(mainConfigPath); + if (!main.hasDefaultExport) { + once.warn(dedent` + Your main.js is not using a default export, which is the recommended format. Please update it. + For more info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#esm-format-in-mainjs + `); + } } } diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts index bac27a0069b6..da8e2d2c2972 100644 --- a/code/lib/core-server/src/build-dev.ts +++ b/code/lib/core-server/src/build-dev.ts @@ -67,7 +67,7 @@ export async function buildDevStandalone( options.serverChannelUrl = getServerChannelUrl(port, options); /* eslint-enable no-param-reassign */ - const { framework } = loadMainConfig(options); + const { framework } = await loadMainConfig(options); const corePresets = []; const frameworkName = typeof framework === 'string' ? framework : framework?.name; diff --git a/code/lib/core-server/src/build-static.ts b/code/lib/core-server/src/build-static.ts index 78bffa6c28c0..f8f651a05c2b 100644 --- a/code/lib/core-server/src/build-static.ts +++ b/code/lib/core-server/src/build-static.ts @@ -63,7 +63,7 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption await emptyDir(options.outputDir); await ensureDir(options.outputDir); - const { framework } = loadMainConfig(options); + const { framework } = await loadMainConfig(options); const corePresets = []; const frameworkName = typeof framework === 'string' ? framework : framework?.name; diff --git a/code/lib/csf-tools/src/ConfigFile.ts b/code/lib/csf-tools/src/ConfigFile.ts index d0ac7daf02be..caaccf2ae7b8 100644 --- a/code/lib/csf-tools/src/ConfigFile.ts +++ b/code/lib/csf-tools/src/ConfigFile.ts @@ -119,6 +119,8 @@ export class ConfigFile { fileName?: string; + hasDefaultExport = false; + constructor(ast: t.File, code: string, fileName?: string) { this._ast = ast; this._code = code; @@ -131,6 +133,7 @@ export class ConfigFile { traverse.default(this._ast, { ExportDefaultDeclaration: { enter({ node, parent }) { + self.hasDefaultExport = true; const decl = t.isIdentifier(node.declaration) && t.isProgram(parent) ? _findVarInitialization(node.declaration.name, parent) diff --git a/code/lib/telemetry/src/storybook-metadata.ts b/code/lib/telemetry/src/storybook-metadata.ts index 6973345880e6..f0445252acf9 100644 --- a/code/lib/telemetry/src/storybook-metadata.ts +++ b/code/lib/telemetry/src/storybook-metadata.ts @@ -189,7 +189,7 @@ export const getStorybookMetadata = async (_configDir?: string) => { '--config-dir' ) as string)) ?? '.storybook'; - const mainConfig = loadMainConfig({ configDir }); + const mainConfig = await loadMainConfig({ configDir }); cachedMetadata = await computeStorybookMetadata({ mainConfig, packageJson }); return cachedMetadata; }; diff --git a/code/yarn.lock b/code/yarn.lock index 0c4f258da6fb..30ab5c441f63 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6062,6 +6062,7 @@ __metadata: resolution: "@storybook/core-common@workspace:lib/core-common" dependencies: "@babel/core": ^7.20.2 + "@storybook/csf-tools": 7.0.0-beta.38 "@storybook/node-logger": 7.0.0-beta.38 "@storybook/types": 7.0.0-beta.38 "@types/babel__core": ^7.1.20 @@ -6077,7 +6078,7 @@ __metadata: file-system-cache: ^2.0.0 find-up: ^5.0.0 fs-extra: ^11.1.0 - glob: ^7.1.6 + glob-promise: ^4.2.0 handlebars: ^4.7.7 lazy-universal-dotenv: ^4.0.0 mock-fs: ^5.2.0