diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1bffa805860..5143f97018fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+## 8.2.3
+
+- Bug: Fix invalid docs links in Configure.mdx template page - [#28560](https://github.com/storybookjs/storybook/pull/28560), thanks @kylegach!
+- CLI: Add "missing-storybook-dependencies" automigration - [#28579](https://github.com/storybookjs/storybook/pull/28579), thanks @yannbf!
+- CPC: Add `theming/create` aliases in docs preset - [#28570](https://github.com/storybookjs/storybook/pull/28570), thanks @ndelangen!
+- CPC: Fix incorrect re-export in `core-events` - [#28573](https://github.com/storybookjs/storybook/pull/28573), thanks @ndelangen!
+- CPC: Fix Vite builder had wrong conditions - [#28581](https://github.com/storybookjs/storybook/pull/28581), thanks @ndelangen!
+- CSF: Fix small typing issue - [#28587](https://github.com/storybookjs/storybook/pull/28587), thanks @valentinpalkovic!
+- Portable stories: Remove unused types - [#28548](https://github.com/storybookjs/storybook/pull/28548), thanks @kasperpeulen!
+- Webpack: Fix sourceMap generation in csf-tools - [#28585](https://github.com/storybookjs/storybook/pull/28585), thanks @valentinpalkovic!
+
## 8.2.2
- CPC: Add `ESM` export to `docs-tools` & `node-logger` packages - [#28539](https://github.com/storybookjs/storybook/pull/28539), thanks @ndelangen!
diff --git a/MIGRATION.md b/MIGRATION.md
index 33dfe17f0532..3dd1311dd620 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -1,6 +1,7 @@
Migration
- [From version 8.1.x to 8.2.x](#from-version-81x-to-82x)
+ - [Failed to resolve import "@storybook/X" error](#failed-to-resolve-import-storybookx-error)
- [Preview.js globals renamed to initialGlobals](#previewjs-globals-renamed-to-initialglobals)
- [From version 8.0.x to 8.1.x](#from-version-80x-to-81x)
- [Portable stories](#portable-stories)
@@ -415,6 +416,26 @@
## From version 8.1.x to 8.2.x
+### Failed to resolve import "@storybook/X" error
+
+Storybook's package structure changed in 8.2. It is a non-breaking change, but can expose missing project dependencies.
+
+This happens when `@storybook/X` is missing in your `package.json`, but your project references `@storybook/X` in your source code (typically in a story file or in a `.storybook` config file). This is a problem with your project, and if it worked in earlier versions of Storybook, it was purely accidental.
+
+Now in Storybook 8.2, that incorrect project configuration no longer works. The solution is to install `@storybook/X` as a dev dependency and re-run.
+
+Example errors:
+
+```sh
+Cannot find module @storybook/preview-api or its corresponding type declarations
+```
+
+```sh
+Internal server error: Failed to resolve import "@storybook/theming/create" from ".storybook/theme.ts". Does the file exist?
+```
+
+To protect your project from missing dependencies, try the `no-extraneous-dependencies` rule in [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import).
+
### Preview.js globals renamed to initialGlobals
Starting in 8.2 `preview.js` `globals` are deprecated and have been renamed to `initialGlobals`. We will remove `preview.js` `globals` in 9.0.
diff --git a/code/addons/docs/src/preset.ts b/code/addons/docs/src/preset.ts
index 9f50f7d9a254..0ad19b34bd58 100644
--- a/code/addons/docs/src/preset.ts
+++ b/code/addons/docs/src/preset.ts
@@ -70,6 +70,8 @@ async function webpack(
*/
const cliPath = require.resolve('storybook/package.json');
const themingPath = join(cliPath, '..', 'core', 'theming', 'index.js');
+ const themingCreatePath = join(cliPath, 'core', 'theming', 'create.js');
+
const componentsPath = join(cliPath, '..', 'core', 'components', 'index.js');
const blocksPath = dirname(require.resolve('@storybook/blocks/package.json'));
if (Array.isArray(webpackConfig.resolve?.alias)) {
@@ -87,6 +89,10 @@ async function webpack(
name: '@mdx-js/react',
alias: mdx,
},
+ {
+ name: '@storybook/theming/create',
+ alias: themingCreatePath,
+ },
{
name: '@storybook/theming',
alias: themingPath,
@@ -104,6 +110,7 @@ async function webpack(
alias = {
...webpackConfig.resolve?.alias,
react,
+ '@storybook/theming/create': themingCreatePath,
'@storybook/theming': themingPath,
'@storybook/components': componentsPath,
'@storybook/blocks': blocksPath,
@@ -168,6 +175,7 @@ export const viteFinal = async (config: any, options: Options) => {
const cliPath = dirname(require.resolve('storybook/package.json'));
const themingPath = join(cliPath, 'core', 'theming', 'index.js');
+ const themingCreatePath = join(cliPath, 'core', 'theming', 'create.js');
const componentsPath = join(cliPath, 'core', 'components', 'index.js');
const blocksPath = dirname(require.resolve('@storybook/blocks/package.json'));
@@ -187,6 +195,7 @@ export const viteFinal = async (config: any, options: Options) => {
*
* In the future the `@storybook/theming` and `@storybook/components` can be removed, as they should be singletons in the future due to the peerDependency on `storybook` package.
*/
+ '@storybook/theming/create': themingCreatePath,
'@storybook/theming': themingPath,
'@storybook/components': componentsPath,
'@storybook/blocks': blocksPath,
diff --git a/code/builders/builder-vite/src/vite-config.ts b/code/builders/builder-vite/src/vite-config.ts
index dd06ce60155a..2a965dbacffc 100644
--- a/code/builders/builder-vite/src/vite-config.ts
+++ b/code/builders/builder-vite/src/vite-config.ts
@@ -65,7 +65,7 @@ export async function commonConfig(
base: './',
plugins: await pluginConfig(options),
resolve: {
- conditions: ['storybook', 'stories', 'test', 'browser', 'import', 'module', 'default'],
+ conditions: ['storybook', 'stories', 'test'],
preserveSymlinks: isPreservingSymlinks(),
alias: {
assert: require.resolve('browser-assert'),
diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts
index 66ac85860e72..1000cc7bf174 100644
--- a/code/core/src/common/js-package-manager/JsPackageManager.ts
+++ b/code/core/src/common/js-package-manager/JsPackageManager.ts
@@ -500,6 +500,10 @@ export abstract class JsPackageManager {
stdio?: 'inherit' | 'pipe'
): string;
public abstract findInstallations(pattern?: string[]): Promise;
+ public abstract findInstallations(
+ pattern?: string[],
+ options?: { depth: number }
+ ): Promise;
public abstract parseErrorFromLogs(logs?: string): string;
public executeCommandSync({
diff --git a/code/core/src/common/js-package-manager/NPMProxy.ts b/code/core/src/common/js-package-manager/NPMProxy.ts
index 09379285d276..ff77aedfa95a 100644
--- a/code/core/src/common/js-package-manager/NPMProxy.ts
+++ b/code/core/src/common/js-package-manager/NPMProxy.ts
@@ -132,12 +132,12 @@ export class NPMProxy extends JsPackageManager {
});
}
- public async findInstallations(pattern: string[]) {
- const exec = async ({ depth }: { depth: number }) => {
+ public async findInstallations(pattern: string[], { depth = 99 }: { depth?: number } = {}) {
+ const exec = async ({ packageDepth }: { packageDepth: number }) => {
const pipeToNull = platform() === 'win32' ? '2>NUL' : '2>/dev/null';
return this.executeCommand({
command: 'npm',
- args: ['ls', '--json', `--depth=${depth}`, pipeToNull],
+ args: ['ls', '--json', `--depth=${packageDepth}`, pipeToNull],
env: {
FORCE_COLOR: 'false',
},
@@ -145,7 +145,7 @@ export class NPMProxy extends JsPackageManager {
};
try {
- const commandResult = await exec({ depth: 99 });
+ const commandResult = await exec({ packageDepth: depth });
const parsedOutput = JSON.parse(commandResult);
return this.mapDependencies(parsedOutput, pattern);
@@ -153,7 +153,7 @@ export class NPMProxy extends JsPackageManager {
// when --depth is higher than 0, npm can return a non-zero exit code
// in case the user's project has peer dependency issues. So we try again with no depth
try {
- const commandResult = await exec({ depth: 0 });
+ const commandResult = await exec({ packageDepth: 0 });
const parsedOutput = JSON.parse(commandResult);
return this.mapDependencies(parsedOutput, pattern);
diff --git a/code/core/src/common/js-package-manager/PNPMProxy.ts b/code/core/src/common/js-package-manager/PNPMProxy.ts
index c44172aebb86..41c2858763c8 100644
--- a/code/core/src/common/js-package-manager/PNPMProxy.ts
+++ b/code/core/src/common/js-package-manager/PNPMProxy.ts
@@ -98,16 +98,16 @@ export class PNPMProxy extends JsPackageManager {
});
}
- public async findInstallations(pattern: string[]) {
- const commandResult = await this.executeCommand({
- command: 'pnpm',
- args: ['list', pattern.map((p) => `"${p}"`).join(' '), '--json', '--depth=99'],
- env: {
- FORCE_COLOR: 'false',
- },
- });
-
+ public async findInstallations(pattern: string[], { depth = 99 }: { depth?: number } = {}) {
try {
+ const commandResult = await this.executeCommand({
+ command: 'pnpm',
+ args: ['list', pattern.map((p) => `"${p}"`).join(' '), '--json', `--depth=${depth}`],
+ env: {
+ FORCE_COLOR: 'false',
+ },
+ });
+
const parsedOutput = JSON.parse(commandResult);
return this.mapDependencies(parsedOutput, pattern);
} catch (e) {
diff --git a/code/core/src/common/js-package-manager/Yarn1Proxy.ts b/code/core/src/common/js-package-manager/Yarn1Proxy.ts
index 9924afd0fb91..b193d4db4f15 100644
--- a/code/core/src/common/js-package-manager/Yarn1Proxy.ts
+++ b/code/core/src/common/js-package-manager/Yarn1Proxy.ts
@@ -83,16 +83,22 @@ export class Yarn1Proxy extends JsPackageManager {
return JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as Record;
}
- public async findInstallations(pattern: string[]) {
- const commandResult = await this.executeCommand({
- command: 'yarn',
- args: ['list', '--pattern', pattern.map((p) => `"${p}"`).join(' '), '--recursive', '--json'],
- env: {
- FORCE_COLOR: 'false',
- },
- });
+ public async findInstallations(pattern: string[], { depth = 99 }: { depth?: number } = {}) {
+ const yarnArgs = ['list', '--pattern', pattern.map((p) => `"${p}"`).join(' '), '--json'];
+
+ if (depth !== 0) {
+ yarnArgs.push('--recursive');
+ }
try {
+ const commandResult = await this.executeCommand({
+ command: 'yarn',
+ args: yarnArgs.concat(pattern),
+ env: {
+ FORCE_COLOR: 'false',
+ },
+ });
+
const parsedOutput = JSON.parse(commandResult);
return this.mapDependencies(parsedOutput, pattern);
} catch (e) {
diff --git a/code/core/src/common/js-package-manager/Yarn2Proxy.ts b/code/core/src/common/js-package-manager/Yarn2Proxy.ts
index acd1b9bbfcdf..b8ea0f40a66f 100644
--- a/code/core/src/common/js-package-manager/Yarn2Proxy.ts
+++ b/code/core/src/common/js-package-manager/Yarn2Proxy.ts
@@ -121,16 +121,22 @@ export class Yarn2Proxy extends JsPackageManager {
return this.executeCommand({ command: 'yarn', args: [command, ...args], cwd });
}
- public async findInstallations(pattern: string[]) {
- const commandResult = await this.executeCommand({
- command: 'yarn',
- args: ['info', '--name-only', '--recursive', ...pattern],
- env: {
- FORCE_COLOR: 'false',
- },
- });
+ public async findInstallations(pattern: string[], { depth = 99 }: { depth?: number } = {}) {
+ const yarnArgs = ['info', '--name-only'];
+
+ if (depth !== 0) {
+ yarnArgs.push('--recursive');
+ }
try {
+ const commandResult = await this.executeCommand({
+ command: 'yarn',
+ args: yarnArgs.concat(pattern),
+ env: {
+ FORCE_COLOR: 'false',
+ },
+ });
+
return this.mapDependencies(commandResult, pattern);
} catch (e) {
return undefined;
diff --git a/code/core/src/csf-tools/CsfFile.ts b/code/core/src/csf-tools/CsfFile.ts
index f748d1d2d4ba..2ab3bfa27408 100644
--- a/code/core/src/csf-tools/CsfFile.ts
+++ b/code/core/src/csf-tools/CsfFile.ts
@@ -3,7 +3,7 @@ import { readFile, writeFile } from 'node:fs/promises';
import { dedent } from 'ts-dedent';
import * as t from '@babel/types';
-import bg from '@babel/generator';
+import bg, { type GeneratorOptions } from '@babel/generator';
import bt from '@babel/traverse';
import * as recast from 'recast';
@@ -599,15 +599,9 @@ export const loadCsf = (code: string, options: CsfOptions) => {
return new CsfFile(ast, options);
};
-interface FormatOptions {
- sourceMaps?: boolean;
- preserveStyle?: boolean;
- inputSourceMap?: any;
-}
-
export const formatCsf = (
csf: CsfFile,
- options: FormatOptions = { sourceMaps: false },
+ options: GeneratorOptions & { inputSourceMap?: any } = { sourceMaps: false },
code?: string
) => {
const result = generate(csf._ast, options, code);
diff --git a/code/core/src/preview-api/modules/store/csf/portable-stories.ts b/code/core/src/preview-api/modules/store/csf/portable-stories.ts
index 647fa492a0e1..37893aa4c035 100644
--- a/code/core/src/preview-api/modules/store/csf/portable-stories.ts
+++ b/code/core/src/preview-api/modules/store/csf/portable-stories.ts
@@ -263,10 +263,7 @@ type UnwrappedJSXStoryRef = {
__pw_type: 'jsx';
type: UnwrappedImportStoryRef;
};
-type UnwrappedImportStoryRef = ComposedStoryFn & {
- playPromise?: Promise;
- renderingEnded?: PromiseWithResolvers;
-};
+type UnwrappedImportStoryRef = ComposedStoryFn;
declare global {
function __pwUnwrapObject(
diff --git a/code/deprecated/core-events/shim.js b/code/deprecated/core-events/shim.js
index 4c4b44a5716d..217389a630ed 100644
--- a/code/deprecated/core-events/shim.js
+++ b/code/deprecated/core-events/shim.js
@@ -1 +1 @@
-module.exports = require('storybook/internal/core-errors');
+module.exports = require('storybook/internal/core-events');
diff --git a/code/frameworks/nextjs/template/cli/js/Configure.mdx b/code/frameworks/nextjs/template/cli/js/Configure.mdx
index 055a3c564efc..cc3292373f73 100644
--- a/code/frameworks/nextjs/template/cli/js/Configure.mdx
+++ b/code/frameworks/nextjs/template/cli/js/Configure.mdx
@@ -52,7 +52,7 @@ export const RightArrow = () =>