Repository: storybookjs/storybook
File: code/core/src/common/utils/load-main-config.ts (TypeScript)

Code before:

import { importModule } from '../../shared/utils/module';
import { getInterpretedFile } from './interpret-files';
import { validateConfigurationFiles } from './validate-configuration-files';

export async function loadMainConfig({
  configDir = '.storybook',
  cwd,
}: {
  configDir: string;
  cwd?: string;
}): Promise<StorybookConfig> {
  await validateConfigurationFiles(configDir, cwd);

  const mainPath = getInterpretedFile(resolve(configDir, 'main')) as string;

  try {
    const out = await importModule(mainPath);
    return out;
  } catch (e) {
    if (!(e instanceof Error)) {
      throw e;
    }
    if (e.message.includes('require is not defined')) {
      logger.info(
        'loading main config failed, trying a temporary fix, please ensure the main config is valid ESM'
      );
      const comment =
        '// end of storybook 10 migration assistant header, you can delete the above code';
      const content = await readFile(mainPath, 'utf-8');

      if (!content.includes(comment)) {
        const header = dedent`
          import { createRequire } from "node:module";
          import { dirname } from "node:path";
          import { fileURLToPath } from "node:url";
    
          const __filename = fileURLToPath(import.meta.url);
          const __dirname = dirname(__filename);
          const require = createRequire(import.meta.url);
        `;

        const { ext, name, dir } = parse(mainPath);
        const modifiedMainPath = join(dir, `${name}.tmp.${ext}`);
        await writeFile(modifiedMainPath, [header, comment, content].join('\n\n'));
        const out = await importModule(modifiedMainPath);
        await rm(modifiedMainPath);
        return out;
      }
    }


Review comment (bug):
```suggestion
        'Loading main config failed, trying a temporary fix. Please ensure the main config is valid ESM'
```

Code after:

import { importModule } from '../../shared/utils/module';
import { getInterpretedFile } from './interpret-files';
import { validateConfigurationFiles } from './validate-configuration-files';

export async function loadMainConfig({
  configDir = '.storybook',
  cwd,
}: {
  configDir: string;
  cwd?: string;
}): Promise<StorybookConfig> {
  await validateConfigurationFiles(configDir, cwd);

  const mainPath = getInterpretedFile(resolve(configDir, 'main')) as string;

  try {
    const out = await importModule(mainPath);
    return out;
  } catch (e) {
    if (!(e instanceof Error)) {
      throw e;
    }
    if (e.message.includes('require is not defined')) {
      logger.info(
        'Loading main config failed, trying a temporary fix, Please ensure the main config is valid ESM'
      );
      const comment =
        '// end of Storybook 10 migration assistant header, you can delete the above code';
      const content = await readFile(mainPath, 'utf-8');

      if (!content.includes(comment)) {
        const header = dedent`
          import { createRequire } from "node:module";
          import { dirname } from "node:path";
          import { fileURLToPath } from "node:url";
    
          const __filename = fileURLToPath(import.meta.url);
          const __dirname = dirname(__filename);
          const require = createRequire(import.meta.url);
        `;

        const { ext, name, dir } = parse(mainPath);
        const modifiedMainPath = join(dir, `${name}.tmp.${ext}`);
        await writeFile(modifiedMainPath, [header, comment, content].join('\n\n'));
        let out;
        try {
          out = await importModule(modifiedMainPath);
        } finally {
          await rm(modifiedMainPath);
        }