diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index cd45f1d91c8e..bc054af85364 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -52,6 +52,19 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index 2584ee916f76..d22a8221a947 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -51,6 +51,19 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index c51bf2682882..a1e4cfb6de9e 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -46,6 +46,16 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index 7445ad9c83d3..c915c55daee0 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -27,6 +27,76 @@ "import": "./dist/index.mjs", "types": "./dist/index.d.ts" }, + "./actions/preview": { + "require": "./dist/actions/preview.js", + "import": "./dist/actions/preview.mjs", + "types": "./dist/actions/preview.d.ts" + }, + "./actions/manager": { + "require": "./dist/actions/manager.js", + "import": "./dist/actions/manager.mjs", + "types": "./dist/actions/manager.d.ts" + }, + "./backgrounds/preview": { + "require": "./dist/backgrounds/preview.js", + "import": "./dist/backgrounds/preview.mjs", + "types": "./dist/backgrounds/preview.d.ts" + }, + "./backgrounds/manager": { + "require": "./dist/backgrounds/manager.js", + "import": "./dist/backgrounds/manager.mjs", + "types": "./dist/backgrounds/manager.d.ts" + }, + "./controls/manager": { + "require": "./dist/controls/manager.js", + "import": "./dist/controls/manager.mjs", + "types": "./dist/controls/manager.d.ts" + }, + "./docs/preview": { + "require": "./dist/docs/preview.js", + "import": "./dist/docs/preview.mjs", + "types": "./dist/docs/preview.d.ts" + }, + "./docs/preset": { + "require": "./dist/docs/preset.js", + "import": "./dist/docs/preset.mjs", + "types": "./dist/docs/preset.d.ts" + }, + "./highlight/preview": { + "require": "./dist/highlight/preview.js", + "import": "./dist/highlight/preview.mjs", + "types": "./dist/highlight/preview.d.ts" + }, + "./measure/preview": { + "require": "./dist/measure/preview.js", + "import": "./dist/measure/preview.mjs", + "types": "./dist/measure/preview.d.ts" + }, + "./measure/manager": { + "require": "./dist/measure/manager.js", + "import": "./dist/measure/manager.mjs", + "types": "./dist/measure/manager.d.ts" + }, + "./outline/preview": { + "require": "./dist/outline/preview.js", + "import": "./dist/outline/preview.mjs", + "types": "./dist/outline/preview.d.ts" + }, + "./outline/manager": { + "require": "./dist/outline/manager.js", + "import": "./dist/outline/manager.mjs", + "types": "./dist/outline/manager.d.ts" + }, + "./toolbars/manager": { + "require": "./dist/toolbars/manager.js", + "import": "./dist/toolbars/manager.mjs", + "types": "./dist/toolbars/manager.d.ts" + }, + "./viewport/manager": { + "require": "./dist/viewport/manager.js", + "import": "./dist/viewport/manager.mjs", + "types": "./dist/viewport/manager.d.ts" + }, "./package.json": "./package.json" }, "main": "dist/index.js", @@ -108,7 +178,21 @@ }, "bundler": { "entries": [ - "./src/index.ts" + "./src/index.ts", + "./src/actions/preview.ts", + "./src/actions/manager.ts", + "./src/backgrounds/preview.ts", + "./src/backgrounds/manager.ts", + "./src/controls/manager.ts", + "./src/docs/preview.ts", + "./src/docs/preset.ts", + "./src/highlight/preview.ts", + "./src/measure/preview.ts", + "./src/measure/manager.ts", + "./src/outline/preview.ts", + "./src/outline/manager.ts", + "./src/toolbars/manager.ts", + "./src/viewport/manager.ts" ], "platform": "node" }, diff --git a/code/addons/essentials/src/actions/manager.ts b/code/addons/essentials/src/actions/manager.ts new file mode 100644 index 000000000000..7e125b743169 --- /dev/null +++ b/code/addons/essentials/src/actions/manager.ts @@ -0,0 +1,2 @@ +// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762 +export * from '@storybook/addon-actions/manager'; diff --git a/code/addons/essentials/src/actions/preview.ts b/code/addons/essentials/src/actions/preview.ts new file mode 100644 index 000000000000..86c6d5f2e656 --- /dev/null +++ b/code/addons/essentials/src/actions/preview.ts @@ -0,0 +1,4 @@ +/* eslint-disable import/export */ +// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered + +export * from '@storybook/addon-actions/preview'; diff --git a/code/addons/essentials/src/backgrounds/manager.ts b/code/addons/essentials/src/backgrounds/manager.ts new file mode 100644 index 000000000000..bc51f1b22b4e --- /dev/null +++ b/code/addons/essentials/src/backgrounds/manager.ts @@ -0,0 +1,2 @@ +// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762 +export * from '@storybook/addon-backgrounds/manager'; diff --git a/code/addons/essentials/src/backgrounds/preview.ts b/code/addons/essentials/src/backgrounds/preview.ts new file mode 100644 index 000000000000..5e56121e4a03 --- /dev/null +++ b/code/addons/essentials/src/backgrounds/preview.ts @@ -0,0 +1,4 @@ +/* eslint-disable import/export */ +// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered + +export * from '@storybook/addon-backgrounds/preview'; diff --git a/code/addons/essentials/src/controls/manager.ts b/code/addons/essentials/src/controls/manager.ts new file mode 100644 index 000000000000..49e403523565 --- /dev/null +++ b/code/addons/essentials/src/controls/manager.ts @@ -0,0 +1,2 @@ +// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762 +export * from '@storybook/addon-controls/manager'; diff --git a/code/addons/essentials/src/docs/preset.ts b/code/addons/essentials/src/docs/preset.ts new file mode 100644 index 000000000000..f97114783e13 --- /dev/null +++ b/code/addons/essentials/src/docs/preset.ts @@ -0,0 +1 @@ +export * from '@storybook/addon-docs/preset'; diff --git a/code/addons/essentials/src/docs/preview.ts b/code/addons/essentials/src/docs/preview.ts new file mode 100644 index 000000000000..68ad94fc557c --- /dev/null +++ b/code/addons/essentials/src/docs/preview.ts @@ -0,0 +1 @@ +export * from '@storybook/addon-docs/preview'; diff --git a/code/addons/essentials/src/highlight/preview.ts b/code/addons/essentials/src/highlight/preview.ts new file mode 100644 index 000000000000..ffcf62555af2 --- /dev/null +++ b/code/addons/essentials/src/highlight/preview.ts @@ -0,0 +1,4 @@ +/* eslint-disable import/export */ +// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered + +export * from '@storybook/addon-highlight/preview'; diff --git a/code/addons/essentials/src/index.ts b/code/addons/essentials/src/index.ts index 861fd91162da..96fd171146bb 100644 --- a/code/addons/essentials/src/index.ts +++ b/code/addons/essentials/src/index.ts @@ -1,4 +1,4 @@ -import path, { dirname, join } from 'path'; +import path from 'path'; import { logger } from '@storybook/node-logger'; import { serverRequire } from '@storybook/core-common'; @@ -24,7 +24,8 @@ const requireMain = (configDir: string) => { }; export function addons(options: PresetOptions) { - const checkInstalled = (addon: string, main: any) => { + const checkInstalled = (addonName: string, main: any) => { + const addon = `@storybook/addon-${addonName}`; const existingAddon = main.addons?.find((entry: string | { name: string }) => { const name = typeof entry === 'string' ? entry : entry.name; return name?.startsWith(addon); @@ -36,35 +37,21 @@ export function addons(options: PresetOptions) { }; const main = requireMain(options.configDir); - return ( - [ - 'docs', - 'controls', - 'actions', - 'backgrounds', - 'viewport', - 'toolbars', - 'measure', - 'outline', - 'highlight', - ] - .filter((key) => (options as any)[key] !== false) - .map((key) => `@storybook/addon-${key}`) - .filter((addon) => !checkInstalled(addon, main)) - // Use `require.resolve` to ensure Yarn PnP compatibility - // Files of various addons should be resolved in the context of `addon-essentials` as they are listed as deps here - // and not in `@storybook/core` nor in SB user projects. If `@storybook/core` make the require itself Yarn 2 will - // throw an error saying that the package to require must be added as a dependency. Doing `require.resolve` will - // allow `@storybook/core` to work with absolute path directly, no more require of dep no more issue. - // File to load can be `preset.js`, `register.js`, or the package entry point, so we need to check all these cases - // as it's done in `lib/core/src/server/presets.js`. - .map((addon) => { - try { - return dirname(require.resolve(join(addon, 'package.json'))); - // eslint-disable-next-line no-empty - } catch (err) {} - - return require.resolve(addon); - }) - ); + return [ + 'docs', + 'controls', + 'actions', + 'backgrounds', + 'viewport', + 'toolbars', + 'measure', + 'outline', + 'highlight', + ] + .filter((key) => (options as any)[key] !== false) + .filter((addon) => !checkInstalled(addon, main)) + .map((addon) => { + // We point to the re-export from addon-essentials to support yarn pnp and pnpm. + return `@storybook/addon-essentials/${addon}`; + }); } diff --git a/code/addons/essentials/src/measure/manager.ts b/code/addons/essentials/src/measure/manager.ts new file mode 100644 index 000000000000..cf95d95a76da --- /dev/null +++ b/code/addons/essentials/src/measure/manager.ts @@ -0,0 +1,2 @@ +// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762 +export * from '@storybook/addon-measure/manager'; diff --git a/code/addons/essentials/src/measure/preview.ts b/code/addons/essentials/src/measure/preview.ts new file mode 100644 index 000000000000..f18769ff001a --- /dev/null +++ b/code/addons/essentials/src/measure/preview.ts @@ -0,0 +1,4 @@ +/* eslint-disable import/export */ +// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered + +export * from '@storybook/addon-measure/preview'; diff --git a/code/addons/essentials/src/outline/manager.ts b/code/addons/essentials/src/outline/manager.ts new file mode 100644 index 000000000000..07a0a1e4879a --- /dev/null +++ b/code/addons/essentials/src/outline/manager.ts @@ -0,0 +1,2 @@ +// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762 +export * from '@storybook/addon-outline/manager'; diff --git a/code/addons/essentials/src/outline/preview.ts b/code/addons/essentials/src/outline/preview.ts new file mode 100644 index 000000000000..1cc44b9689a8 --- /dev/null +++ b/code/addons/essentials/src/outline/preview.ts @@ -0,0 +1,4 @@ +/* eslint-disable import/export */ +// TODO: We need to configure an eslint-import typescript resolver for export maps to be considered + +export * from '@storybook/addon-outline/preview'; diff --git a/code/addons/essentials/src/toolbars/manager.ts b/code/addons/essentials/src/toolbars/manager.ts new file mode 100644 index 000000000000..8c4868b1e254 --- /dev/null +++ b/code/addons/essentials/src/toolbars/manager.ts @@ -0,0 +1,2 @@ +// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762 +export * from '@storybook/addon-toolbars/manager'; diff --git a/code/addons/essentials/src/typings.d.ts b/code/addons/essentials/src/typings.d.ts index 8cf1e5fe3055..818a79e77c49 100644 --- a/code/addons/essentials/src/typings.d.ts +++ b/code/addons/essentials/src/typings.d.ts @@ -1 +1,5 @@ declare module 'fs'; + +// TODO: Remove this once addon-docs is generated with tsup +declare module '@storybook/addon-docs/preview'; +declare module '@storybook/addon-docs/preset'; diff --git a/code/addons/essentials/src/viewport/manager.ts b/code/addons/essentials/src/viewport/manager.ts new file mode 100644 index 000000000000..7c052f303800 --- /dev/null +++ b/code/addons/essentials/src/viewport/manager.ts @@ -0,0 +1,2 @@ +// @ts-expect-error The generated definition file is empty. https://github.com/egoist/tsup/issues/762 +export * from '@storybook/addon-viewport/manager'; diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index c8a7d9ef48e6..89ae9a2420db 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -30,15 +30,25 @@ "types": "./dist/index.d.ts" }, "./preview": { - "require": "./dist/highlight.js", - "import": "./dist/highlight.mjs", - "types": "./dist/highlight.d.ts" + "require": "./dist/preview.js", + "import": "./dist/preview.mjs", + "types": "./dist/preview.d.ts" }, "./package.json": "./package.json" }, "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", @@ -64,7 +74,7 @@ "bundler": { "entries": [ "./src/index.ts", - "./src/highlight.ts" + "./src/preview.ts" ] }, "gitHead": "b58a29b785462f8a8b711b6bb2d7223fd6dc17fd", diff --git a/code/addons/highlight/preview.js b/code/addons/highlight/preview.js index f7dfc599138c..49ad602f79f4 100644 --- a/code/addons/highlight/preview.js +++ b/code/addons/highlight/preview.js @@ -1 +1 @@ -export * from './dist/highlight'; +export * from './dist/preview'; diff --git a/code/addons/highlight/src/highlight.ts b/code/addons/highlight/src/preview.ts similarity index 100% rename from code/addons/highlight/src/highlight.ts rename to code/addons/highlight/src/preview.ts diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 0eb7130861b4..ca295f478bbd 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -33,9 +33,9 @@ "types": "./dist/manager.d.ts" }, "./preview": { - "require": "./dist/preset/preview.js", - "import": "./dist/preset/preview.mjs", - "types": "./dist/preset/preview.d.ts" + "require": "./dist/preview.js", + "import": "./dist/preview.mjs", + "types": "./dist/preview.d.ts" }, "./register.js": { "require": "./dist/manager.js", @@ -47,6 +47,19 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", @@ -99,7 +112,7 @@ "entries": [ "./src/index.ts", "./src/manager.tsx", - "./src/preset/preview.ts", + "./src/preview.ts", "./src/preset/checkActionsLoaded.ts" ], "platform": "node" diff --git a/code/addons/interactions/preview.js b/code/addons/interactions/preview.js index 48714cc6fba3..49ad602f79f4 100644 --- a/code/addons/interactions/preview.js +++ b/code/addons/interactions/preview.js @@ -1 +1 @@ -export * from './dist/preset/preview'; +export * from './dist/preview'; diff --git a/code/addons/interactions/src/preset/preview.ts b/code/addons/interactions/src/preview.ts similarity index 100% rename from code/addons/interactions/src/preset/preview.ts rename to code/addons/interactions/src/preview.ts diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 96f77afe0c62..f795ffdd656a 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -48,6 +48,16 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index 92cc62a00d09..a1aaf60cb8e2 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -52,6 +52,19 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index 6ab70183b27a..10fb28b93983 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -50,6 +50,19 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index 478b1d9b23a6..4337c7e0d74b 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -39,9 +39,9 @@ "types": "./dist/manager.d.ts" }, "./preview": { - "require": "./dist/preset/preview.js", - "import": "./dist/preset/preview.mjs", - "types": "./dist/preset/preview.d.ts" + "require": "./dist/preview.js", + "import": "./dist/preview.mjs", + "types": "./dist/preview.d.ts" }, "./register": { "require": "./dist/manager.js", @@ -53,6 +53,19 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", @@ -95,7 +108,7 @@ "entries": [ "./src/index.ts", "./src/manager.tsx", - "./src/preset/preview.tsx" + "./src/preview.tsx" ] }, "gitHead": "b58a29b785462f8a8b711b6bb2d7223fd6dc17fd", diff --git a/code/addons/outline/preview.js b/code/addons/outline/preview.js index 48714cc6fba3..49ad602f79f4 100644 --- a/code/addons/outline/preview.js +++ b/code/addons/outline/preview.js @@ -1 +1 @@ -export * from './dist/preset/preview'; +export * from './dist/preview'; diff --git a/code/addons/outline/src/preset/preview.tsx b/code/addons/outline/src/preview.tsx similarity index 51% rename from code/addons/outline/src/preset/preview.tsx rename to code/addons/outline/src/preview.tsx index 1abee6e575c6..65161c6c4f29 100644 --- a/code/addons/outline/src/preset/preview.tsx +++ b/code/addons/outline/src/preview.tsx @@ -1,5 +1,5 @@ -import { withOutline } from '../withOutline'; -import { PARAM_KEY } from '../constants'; +import { withOutline } from './withOutline'; +import { PARAM_KEY } from './constants'; export const decorators = [withOutline]; diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index 0b4cbde72ca5..e936e70728f6 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -46,6 +46,16 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 35d69a6bc5b9..3f3408a7be6d 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -48,6 +48,19 @@ "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "dist/index.d.ts" + ], + "manager": [ + "dist/manager.d.ts" + ], + "preview": [ + "dist/preview.d.ts" + ] + } + }, "files": [ "dist/**/*", "README.md", diff --git a/code/frameworks/react-vite/src/index.ts b/code/frameworks/react-vite/src/index.ts index 8fbdfff5e6e2..067a9d564f75 100644 --- a/code/frameworks/react-vite/src/index.ts +++ b/code/frameworks/react-vite/src/index.ts @@ -1,8 +1,13 @@ // exports for builder-vite +import * as clientApi from '@storybook/client-api'; + +// client-api exposes both a class, and individual named exports. +// The class is used in StoryStoreV7 and the individual exports in SSv6 +const { ClientApi } = clientApi; export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage'; export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket'; export { addons } from '@storybook/addons'; export { composeConfigs, PreviewWeb } from '@storybook/preview-web'; -export { ClientApi } from '@storybook/client-api'; +export { clientApi, ClientApi }; export type { StorybookConfig } from '@storybook/builder-vite'; diff --git a/code/frameworks/svelte-vite/src/index.ts b/code/frameworks/svelte-vite/src/index.ts index 8fbdfff5e6e2..067a9d564f75 100644 --- a/code/frameworks/svelte-vite/src/index.ts +++ b/code/frameworks/svelte-vite/src/index.ts @@ -1,8 +1,13 @@ // exports for builder-vite +import * as clientApi from '@storybook/client-api'; + +// client-api exposes both a class, and individual named exports. +// The class is used in StoryStoreV7 and the individual exports in SSv6 +const { ClientApi } = clientApi; export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage'; export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket'; export { addons } from '@storybook/addons'; export { composeConfigs, PreviewWeb } from '@storybook/preview-web'; -export { ClientApi } from '@storybook/client-api'; +export { clientApi, ClientApi }; export type { StorybookConfig } from '@storybook/builder-vite'; diff --git a/code/frameworks/vue-vite/src/index.ts b/code/frameworks/vue-vite/src/index.ts index 8fbdfff5e6e2..067a9d564f75 100644 --- a/code/frameworks/vue-vite/src/index.ts +++ b/code/frameworks/vue-vite/src/index.ts @@ -1,8 +1,13 @@ // exports for builder-vite +import * as clientApi from '@storybook/client-api'; + +// client-api exposes both a class, and individual named exports. +// The class is used in StoryStoreV7 and the individual exports in SSv6 +const { ClientApi } = clientApi; export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage'; export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket'; export { addons } from '@storybook/addons'; export { composeConfigs, PreviewWeb } from '@storybook/preview-web'; -export { ClientApi } from '@storybook/client-api'; +export { clientApi, ClientApi }; export type { StorybookConfig } from '@storybook/builder-vite'; diff --git a/code/frameworks/vue3-vite/src/index.ts b/code/frameworks/vue3-vite/src/index.ts index 8fbdfff5e6e2..067a9d564f75 100644 --- a/code/frameworks/vue3-vite/src/index.ts +++ b/code/frameworks/vue3-vite/src/index.ts @@ -1,8 +1,13 @@ // exports for builder-vite +import * as clientApi from '@storybook/client-api'; + +// client-api exposes both a class, and individual named exports. +// The class is used in StoryStoreV7 and the individual exports in SSv6 +const { ClientApi } = clientApi; export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage'; export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket'; export { addons } from '@storybook/addons'; export { composeConfigs, PreviewWeb } from '@storybook/preview-web'; -export { ClientApi } from '@storybook/client-api'; +export { clientApi, ClientApi }; export type { StorybookConfig } from '@storybook/builder-vite'; diff --git a/code/frameworks/web-components-vite/src/index.ts b/code/frameworks/web-components-vite/src/index.ts index 8fbdfff5e6e2..067a9d564f75 100644 --- a/code/frameworks/web-components-vite/src/index.ts +++ b/code/frameworks/web-components-vite/src/index.ts @@ -1,8 +1,13 @@ // exports for builder-vite +import * as clientApi from '@storybook/client-api'; + +// client-api exposes both a class, and individual named exports. +// The class is used in StoryStoreV7 and the individual exports in SSv6 +const { ClientApi } = clientApi; export { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage'; export { createChannel as createWebSocketChannel } from '@storybook/channel-websocket'; export { addons } from '@storybook/addons'; export { composeConfigs, PreviewWeb } from '@storybook/preview-web'; -export { ClientApi } from '@storybook/client-api'; +export { clientApi, ClientApi }; export type { StorybookConfig } from '@storybook/builder-vite'; diff --git a/code/lib/builder-vite/src/codegen-iframe-script.ts b/code/lib/builder-vite/src/codegen-iframe-script.ts index 141965a0034e..fdfe0249bce5 100644 --- a/code/lib/builder-vite/src/codegen-iframe-script.ts +++ b/code/lib/builder-vite/src/codegen-iframe-script.ts @@ -1,22 +1,23 @@ -import { isAbsolute, resolve } from 'path'; -import { getRendererName } from '@storybook/core-common'; +import { getRendererName, getFrameworkName } from '@storybook/core-common'; +import type { PreviewAnnotation } from '@storybook/types'; import { virtualPreviewFile, virtualStoriesFile } from './virtual-file-names'; -import { transformAbsPath } from './utils/transform-abs-path'; import type { ExtendedOptions } from './types'; +import { processPreviewAnnotation } from './utils/process-preview-annotation'; export async function generateIframeScriptCode(options: ExtendedOptions) { const { presets } = options; const rendererName = await getRendererName(options); - const previewAnnotations = await presets.apply('previewAnnotations', [], options); - const resolvedPreviewAnnotations = previewAnnotations.map((entry) => - isAbsolute(entry) ? entry : resolve(entry) + const frameworkName = await getFrameworkName(options); + + const previewAnnotations = await presets.apply( + 'previewAnnotations', + [], + options ); - const configEntries = [...resolvedPreviewAnnotations].filter(Boolean); + const configEntries = [...previewAnnotations].filter(Boolean).map(processPreviewAnnotation); - const absoluteFilesToImport = (files: string[], name: string) => - files - .map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'${transformAbsPath(el)}'`) - .join('\n'); + const filesToImport = (files: string[], name: string) => + files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'${el}'`).join('\n'); const importArray = (name: string, length: number) => new Array(length).fill(0).map((_, i) => `${name}_${i}`); @@ -28,10 +29,8 @@ export async function generateIframeScriptCode(options: ExtendedOptions) { // Ensure that the client API is initialized by the framework before any other iframe code // is loaded. That way our client-apis can assume the existence of the API+store import { configure } from '${rendererName}'; - - import * as clientApi from "@storybook/client-api"; - import { logger } from '@storybook/client-logger'; - ${absoluteFilesToImport(configEntries, 'config')} + import { clientApi } from '${frameworkName}'; + ${filesToImport(configEntries, 'config')} import * as preview from '${virtualPreviewFile}'; import { configStories } from '${virtualStoriesFile}'; diff --git a/code/lib/builder-vite/src/codegen-modern-iframe-script.ts b/code/lib/builder-vite/src/codegen-modern-iframe-script.ts index ee5339228f23..c1c7aa6a4444 100644 --- a/code/lib/builder-vite/src/codegen-modern-iframe-script.ts +++ b/code/lib/builder-vite/src/codegen-modern-iframe-script.ts @@ -1,21 +1,22 @@ -import { isAbsolute, resolve } from 'path'; import { loadPreviewOrConfigFile, getFrameworkName } from '@storybook/core-common'; +import type { PreviewAnnotation } from '@storybook/types'; import { virtualStoriesFile, virtualAddonSetupFile } from './virtual-file-names'; -import { transformAbsPath } from './utils/transform-abs-path'; import type { ExtendedOptions } from './types'; +import { processPreviewAnnotation } from './utils/process-preview-annotation'; export async function generateModernIframeScriptCode(options: ExtendedOptions) { const { presets, configDir } = options; const frameworkName = await getFrameworkName(options); const previewOrConfigFile = loadPreviewOrConfigFile({ configDir }); - const previewAnnotations = await presets.apply('previewAnnotations', [], options); - const resolvedPreviewAnnotations = [...previewAnnotations].map((entry) => - isAbsolute(entry) ? entry : resolve(entry) + const previewAnnotations = await presets.apply( + 'previewAnnotations', + [], + options ); - const relativePreviewAnnotations = [...resolvedPreviewAnnotations, previewOrConfigFile] + const relativePreviewAnnotations = [...previewAnnotations, previewOrConfigFile] .filter(Boolean) - .map((configEntry) => transformAbsPath(configEntry as string)); + .map(processPreviewAnnotation); // eslint-disable-next-line @typescript-eslint/no-shadow const generateHMRHandler = (frameworkName: string): string => { diff --git a/code/lib/builder-vite/src/utils/process-preview-annotation.ts b/code/lib/builder-vite/src/utils/process-preview-annotation.ts new file mode 100644 index 000000000000..ecf811293ce5 --- /dev/null +++ b/code/lib/builder-vite/src/utils/process-preview-annotation.ts @@ -0,0 +1,33 @@ +import type { PreviewAnnotation } from '@storybook/types'; +import { resolve } from 'path'; + +/** + * Preview annotations can take several forms, and vite needs them to be + * a bit more restrained. + * + * For node_modules, we want bare imports (so vite can process them), + * and for files in the user's source, + * we want absolute paths. + */ +export function processPreviewAnnotation(path: PreviewAnnotation | undefined) { + // If entry is an object, take the first, which is the + // bare (non-absolute) specifier. + // This is so that webpack can use an absolute path, and + // continue supporting super-addons in pnp/pnpm without + // requiring them to re-export their sub-addons as we do + // in addon-essentials. + if (typeof path === 'object') { + return path.bare; + } + // resolve relative paths into absolute paths, but don't resolve "bare" imports + if (path?.startsWith('./') || path?.startsWith('../')) { + return resolve(path); + } + // This should not occur, since we use `.filter(Boolean)` prior to + // calling this function, but this makes typescript happy + if (!path) { + throw new Error('Could not determine path for previewAnnotation'); + } + + return path; +} diff --git a/code/lib/builder-vite/src/utils/transform-abs-path.ts b/code/lib/builder-vite/src/utils/transform-abs-path.ts deleted file mode 100644 index bd8c89f8fbc3..000000000000 --- a/code/lib/builder-vite/src/utils/transform-abs-path.ts +++ /dev/null @@ -1,11 +0,0 @@ -import path from 'path'; -import { normalizePath } from 'vite'; - -// We need to convert from an absolute path, to a traditional node module import path, -// so that vite can correctly pre-bundle/optimize -export function transformAbsPath(absPath: string) { - const splits = absPath.split(`node_modules${path.sep}`); - // Return everything after the final "node_modules/" - const module = normalizePath(splits[splits.length - 1]); - return module; -} diff --git a/code/lib/builder-webpack5/package.json b/code/lib/builder-webpack5/package.json index 4e547eb766ab..16b1c274024c 100644 --- a/code/lib/builder-webpack5/package.json +++ b/code/lib/builder-webpack5/package.json @@ -25,15 +25,15 @@ "import": "./dist/index.mjs", "types": "./dist/index.d.ts" }, - "./presets/custom-webpack-preset.js": { - "require": "./presets/custom-webpack-preset.js", - "import": "./presets/custom-webpack-preset.mjs", - "types": "./presets/custom-webpack-preset.d.ts" + "./presets/custom-webpack-preset": { + "require": "./dist/presets/custom-webpack-preset.js", + "import": "./dist/presets/custom-webpack-preset.mjs", + "types": "./dist/presets/custom-webpack-preset.d.ts" }, - "./presets/preview-preset.js": { - "require": "./presets/preview-preset.js", - "import": "./presets/preview-preset.mjs", - "types": "./presets/preview-preset.d.ts" + "./presets/preview-preset": { + "require": "./dist/presets/preview-preset.js", + "import": "./dist/presets/preview-preset.mjs", + "types": "./dist/presets/preview-preset.d.ts" }, "./templates/virtualModuleModernEntry.js.handlebars": "./templates/virtualModuleModernEntry.js.handlebars", "./package.json": "./package.json" diff --git a/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts index ac29c5ad5d95..a16e9ba8c91e 100644 --- a/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts +++ b/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts @@ -7,7 +7,7 @@ import TerserWebpackPlugin from 'terser-webpack-plugin'; import VirtualModulePlugin from 'webpack-virtual-modules'; import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; -import type { Options, CoreConfig, DocsOptions } from '@storybook/types'; +import type { Options, CoreConfig, DocsOptions, PreviewAnnotation } from '@storybook/types'; import { getRendererName, stringifyProcessEnvs, @@ -82,7 +82,18 @@ export default async ( const docsOptions = await presets.apply('docs'); const previewAnnotations = [ - ...(await presets.apply('previewAnnotations', [], options)), + ...(await presets.apply('previewAnnotations', [], options)).map( + (entry) => { + // If entry is an object, use the absolute import specifier. + // This is to maintain back-compat with community addons that bundle other addons + // and package managers that "hide" sub dependencies (e.g. pnpm / yarn pnp) + // The vite builder uses the bare import specifier. + if (typeof entry === 'object') { + return entry.absolute; + } + return entry; + } + ), loadPreviewOrConfigFile(options), ].filter(Boolean); const entries = (await presets.apply('entries', [], options)) as string[]; diff --git a/code/lib/core-common/src/presets.ts b/code/lib/core-common/src/presets.ts index 2ab9fd3bdc1e..7a3f2ba529ff 100644 --- a/code/lib/core-common/src/presets.ts +++ b/code/lib/core-common/src/presets.ts @@ -1,6 +1,5 @@ import { dedent } from 'ts-dedent'; import { logger } from '@storybook/node-logger'; -import { dirname } from 'path'; import type { BuilderOptions, CLIOptions, @@ -82,35 +81,26 @@ export const resolveAddonName = ( } } - const absolutePackageJson = resolved && resolve(`${name}/package.json`); - - // We want to absolutize the package name part to a path on disk - // (i.e. '/Users/foo/.../node_modules/@addons/foo') as otherwise - // we may not be able to import the package in certain module systems (eg. pnpm, yarn pnp) - const absoluteDir = absolutePackageJson && dirname(absolutePackageJson); - - // If the package has an export (e.g. `/preview`), absolutize it, eg. to - // /Users/foo/.../node_modules/@addons/foo/preview - // NOTE: this looks like the path of an absolute file, but it DOES NOT exist. - // - However it is importable by webpack. - // - Vite needs to strip off the absolute part to import it though - // (vite cannot import absolute files: https://github.com/vitejs/vite/issues/5494 - // this also means vite suffers issues with pnpm etc) - const absolutizeExport = (exportName: string) => { - if (resolve(`${name}${exportName}`)) return `${absoluteDir}${exportName}`; + const checkExists = (exportName: string) => { + if (resolve(`${name}${exportName}`)) return `${name}${exportName}`; return undefined; }; - const path = name; + // This is used to maintain back-compat with community addons that do not + // re-export their sub-addons but reference the sub-addon name directly. + // We need to turn it into an absolute path so that webpack can + // serve it up correctly when yarn pnp or pnpm is being used. + // Vite will be broken in such cases, because it does not process absolute paths, + // and it will try to import from the bare import, breaking in pnp/pnpm. + const absolutizeExport = (exportName: string) => { + return resolve(`${name}${exportName}`); + }; - // We don't want to resolve an import path (e.g. '@addons/foo/preview') to the file on disk, - // because you are not allowed to import arbitrary files in packages in Vite. - // Instead we check if the export exists and "absolutize" it. const managerFile = absolutizeExport(`/manager`); const registerFile = absolutizeExport(`/register`) || absolutizeExport(`/register-panel`); - const previewFile = absolutizeExport(`/preview`); - // Presets are imported by node, so therefore fine to be a path on disk (at this stage anyway) - const presetFile = resolve(`${path}/preset`); + const previewFile = checkExists(`/preview`); + const previewFileAbsolute = absolutizeExport('/preview'); + const presetFile = absolutizeExport(`/preset`); if (!(managerFile || previewFile) && presetFile) { return { @@ -132,9 +122,17 @@ export const resolveAddonName = ( return { type: 'virtual', - name: path, + name, ...(managerEntries.length ? { managerEntries } : {}), - ...(previewFile ? { previewAnnotations: [previewFile] } : {}), + ...(previewFile + ? { + previewAnnotations: [ + previewFileAbsolute + ? { bare: previewFile, absolute: previewFileAbsolute } + : previewFile, + ], + } + : {}), ...(presetFile ? { presets: [{ name: presetFile, options }] } : {}), }; } @@ -233,7 +231,6 @@ export async function loadPreset( logger.warn(warning); logger.error(e); - return []; } } diff --git a/code/lib/docs-tools/src/hasDocsOrControls.ts b/code/lib/docs-tools/src/hasDocsOrControls.ts index d460666d7bc3..b1585ee534d7 100644 --- a/code/lib/docs-tools/src/hasDocsOrControls.ts +++ b/code/lib/docs-tools/src/hasDocsOrControls.ts @@ -1,7 +1,7 @@ import type { Options } from '@storybook/types'; // `addons/x` is for the monorepo, `addon-x` is for normal usage -const packageRe = /(addons\/|addon-)(docs|controls)/; +const packageRe = /(addons\/|addon-|addon-essentials\/)(docs|controls)/; export const hasDocsOrControls = (options: Options) => options.presetsList?.some((preset) => packageRe.test(preset.name)); diff --git a/code/lib/types/src/modules/core-common.ts b/code/lib/types/src/modules/core-common.ts index 5cc04e9c630e..c18b53afb1a7 100644 --- a/code/lib/types/src/modules/core-common.ts +++ b/code/lib/types/src/modules/core-common.ts @@ -462,11 +462,13 @@ export interface CoreCommon_ResolvedAddonPreset { name: string; } +export type PreviewAnnotation = string | { bare: string; absolute: string }; + export interface CoreCommon_ResolvedAddonVirtual { type: 'virtual'; name: string; managerEntries?: string[]; - previewAnnotations?: string[]; + previewAnnotations?: PreviewAnnotation[]; presets?: (string | { name: string; options?: any })[]; }