diff --git a/code/core/src/common/js-package-manager/BUNProxy.ts b/code/core/src/common/js-package-manager/BUNProxy.ts index 3884c175db0b..a2030402413a 100644 --- a/code/core/src/common/js-package-manager/BUNProxy.ts +++ b/code/core/src/common/js-package-manager/BUNProxy.ts @@ -89,7 +89,10 @@ export class BUNProxy extends JsPackageManager { public async getModulePackageJSON(packageName: string): Promise { const wantedPath = join('node_modules', packageName, 'package.json'); - const packageJsonPath = find.up(wantedPath, { cwd: this.cwd, last: getProjectRoot() }); + const packageJsonPath = find.up(wantedPath, { + cwd: this.primaryPackageJson.operationDir, + last: getProjectRoot(), + }); if (!packageJsonPath) { return null; diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts index f749c3283e4a..5afb7b7b77f7 100644 --- a/code/core/src/common/js-package-manager/JsPackageManager.ts +++ b/code/core/src/common/js-package-manager/JsPackageManager.ts @@ -105,7 +105,7 @@ export abstract class JsPackageManager { abstract getRunCommand(command: string): string; /** Get the package.json file for a given module. */ - abstract getModulePackageJSON(packageName: string): Promise; + abstract getModulePackageJSON(packageName: string, cwd?: string): Promise; isStorybookInMonorepo() { const turboJsonPath = find.up(`turbo.json`, { last: getProjectRoot() }); diff --git a/code/core/src/common/js-package-manager/NPMProxy.ts b/code/core/src/common/js-package-manager/NPMProxy.ts index 7444b64f7aea..71ed0790002e 100644 --- a/code/core/src/common/js-package-manager/NPMProxy.ts +++ b/code/core/src/common/js-package-manager/NPMProxy.ts @@ -78,7 +78,10 @@ export class NPMProxy extends JsPackageManager { async getModulePackageJSON(packageName: string): Promise { const wantedPath = join('node_modules', packageName, 'package.json'); - const packageJsonPath = find.up(wantedPath, { cwd: this.cwd, last: getProjectRoot() }); + const packageJsonPath = find.up(wantedPath, { + cwd: this.primaryPackageJson.operationDir, + last: getProjectRoot(), + }); if (!packageJsonPath) { return null; diff --git a/code/core/src/common/js-package-manager/PNPMProxy.ts b/code/core/src/common/js-package-manager/PNPMProxy.ts index 4eb2122c1f83..c781d835daa3 100644 --- a/code/core/src/common/js-package-manager/PNPMProxy.ts +++ b/code/core/src/common/js-package-manager/PNPMProxy.ts @@ -158,7 +158,10 @@ export class PNPMProxy extends JsPackageManager { } const wantedPath = join('node_modules', packageName, 'package.json'); - const packageJsonPath = find.up(wantedPath, { cwd: this.cwd, last: getProjectRoot() }); + const packageJsonPath = find.up(wantedPath, { + cwd: this.primaryPackageJson.operationDir, + last: getProjectRoot(), + }); if (!packageJsonPath) { return null; diff --git a/code/core/src/common/js-package-manager/Yarn1Proxy.ts b/code/core/src/common/js-package-manager/Yarn1Proxy.ts index a13d7a13a9ed..69164b5d493f 100644 --- a/code/core/src/common/js-package-manager/Yarn1Proxy.ts +++ b/code/core/src/common/js-package-manager/Yarn1Proxy.ts @@ -78,7 +78,10 @@ export class Yarn1Proxy extends JsPackageManager { public async getModulePackageJSON(packageName: string): Promise { const wantedPath = join('node_modules', packageName, 'package.json'); - const packageJsonPath = find.up(wantedPath, { cwd: this.cwd, last: getProjectRoot() }); + const packageJsonPath = find.up(wantedPath, { + cwd: this.primaryPackageJson.operationDir, + last: getProjectRoot(), + }); if (!packageJsonPath) { return null; diff --git a/code/core/src/common/js-package-manager/Yarn2Proxy.ts b/code/core/src/common/js-package-manager/Yarn2Proxy.ts index a8d5975cec0a..bba32562b962 100644 --- a/code/core/src/common/js-package-manager/Yarn2Proxy.ts +++ b/code/core/src/common/js-package-manager/Yarn2Proxy.ts @@ -148,7 +148,7 @@ export class Yarn2Proxy extends JsPackageManager { // TODO: Remove pnp compatibility code in SB11 async getModulePackageJSON(packageName: string): Promise { const pnpapiPath = find.any(['.pnp.js', '.pnp.cjs'], { - cwd: this.cwd, + cwd: this.primaryPackageJson.operationDir, last: getProjectRoot(), }); diff --git a/code/core/src/common/utils/cli.ts b/code/core/src/common/utils/cli.ts index 70f5cb76b8bb..9b216fbee848 100644 --- a/code/core/src/common/utils/cli.ts +++ b/code/core/src/common/utils/cli.ts @@ -10,7 +10,6 @@ import uniqueString from 'unique-string'; import type { JsPackageManager } from '../js-package-manager'; import satelliteAddons from '../satellite-addons'; import storybookPackagesVersions from '../versions'; -import { rendererPackages } from './get-storybook-info'; const tempDir = () => realpath(os.tmpdir()); @@ -67,25 +66,6 @@ export function parseList(str: string): string[] { .filter((item) => item.length > 0); } -/** - * Given a package manager, returns the coerced version of Storybook. It tries to find renderer - * packages in the project and returns the coerced version of the first one found. Example: If - * - * @storybook/react version 8.0.0-alpha.14 is installed, it returns the coerced version 8.0.0 - */ -export async function getCoercedStorybookVersion(packageManager: JsPackageManager) { - const packages = ( - await Promise.all( - Object.keys(rendererPackages).map(async (pkg) => ({ - name: pkg, - version: (await packageManager.getModulePackageJSON(pkg))?.version ?? null, - })) - ) - ).filter(({ version }) => !!version); - - return packages[0]?.version || storybookPackagesVersions.storybook; -} - export function getEnvConfig(program: Record, configEnv: Record): void { Object.keys(configEnv).forEach((fieldName) => { const envVarName = configEnv[fieldName]; diff --git a/code/core/src/common/utils/get-storybook-info.ts b/code/core/src/common/utils/get-storybook-info.ts index ad83e36cf00f..88e77f038ba0 100644 --- a/code/core/src/common/utils/get-storybook-info.ts +++ b/code/core/src/common/utils/get-storybook-info.ts @@ -150,12 +150,12 @@ export const getStorybookInfo = async ( const frameworkValue = mainConfig.framework; const frameworkField = typeof frameworkValue === 'string' ? frameworkValue : frameworkValue?.name; const addons = getAddonNames(mainConfig); - const version = getStorybookVersionSpecifier(configDir); + const versionSpecifier = getStorybookVersionSpecifier(configDir); if (!frameworkField) { return { ...configInfo, - version, + versionSpecifier, addons, mainConfig, mainConfigPath: configInfo.mainConfigPath ?? undefined, @@ -183,7 +183,7 @@ export const getStorybookInfo = async ( addons, mainConfig, framework, - version, + versionSpecifier, renderer: renderer ?? undefined, builder: builder ?? undefined, frameworkPackage, diff --git a/code/core/src/telemetry/storybook-metadata.ts b/code/core/src/telemetry/storybook-metadata.ts index 56d4f7a357cb..5d420f2cabfd 100644 --- a/code/core/src/telemetry/storybook-metadata.ts +++ b/code/core/src/telemetry/storybook-metadata.ts @@ -241,7 +241,7 @@ export const computeStorybookMetadata = async ({ portableStoriesFileCount, applicationFileCount, storybookVersion: version, - storybookVersionSpecifier: storybookInfo.version ?? '', + storybookVersionSpecifier: storybookInfo.versionSpecifier ?? '', language, storybookPackages, addons, diff --git a/code/core/src/types/modules/core-common.ts b/code/core/src/types/modules/core-common.ts index 1f4406111ada..3523f60f7f0c 100644 --- a/code/core/src/types/modules/core-common.ts +++ b/code/core/src/types/modules/core-common.ts @@ -684,7 +684,7 @@ export type CoreCommon_AddonInfo = { name: string; inEssentials: boolean }; export interface CoreCommon_StorybookInfo { addons: string[]; - version?: string; + versionSpecifier?: string; framework?: SupportedFramework; renderer?: SupportedRenderer; builder?: SupportedBuilder; diff --git a/code/lib/cli-storybook/src/add.test.ts b/code/lib/cli-storybook/src/add.test.ts index d9a00130ee64..c5554cac28ee 100644 --- a/code/lib/cli-storybook/src/add.test.ts +++ b/code/lib/cli-storybook/src/add.test.ts @@ -85,7 +85,6 @@ vi.mock('storybook/internal/common', () => { getAbsolutePathWrapperName: MockWrapGetAbsolutePathUtils.getAbsolutePathWrapperName, wrapValueWithGetAbsolutePathWrapper: MockWrapGetAbsolutePathUtils.wrapValueWithGetAbsolutePathWrapper, - getCoercedStorybookVersion: vi.fn(() => '8.0.0'), versions: { storybook: '8.0.0', '@storybook/addon-docs': '8.0.0', diff --git a/code/lib/cli-storybook/src/automigrate/fixes/remove-essentials.ts b/code/lib/cli-storybook/src/automigrate/fixes/remove-essentials.ts index 77948f6d458b..9e1151065a42 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/remove-essentials.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/remove-essentials.ts @@ -131,18 +131,11 @@ export const removeEssentials: Fix = { dryRun, packageManager, configDir, - storybookVersion, storiesPaths, mainConfigPath, previewConfigPath, }) { - const { - hasEssentials, - hasDocsDisabled, - hasDocsAddon, - additionalAddonsToRemove, - essentialsOptions, - } = result; + const { hasEssentials, hasDocsDisabled, additionalAddonsToRemove, essentialsOptions } = result; if (!hasEssentials && additionalAddonsToRemove.length === 0) { return; diff --git a/code/lib/cli-storybook/src/automigrate/helpers/mainConfigFile.ts b/code/lib/cli-storybook/src/automigrate/helpers/mainConfigFile.ts index 94e6269fa8bd..647944437211 100644 --- a/code/lib/cli-storybook/src/automigrate/helpers/mainConfigFile.ts +++ b/code/lib/cli-storybook/src/automigrate/helpers/mainConfigFile.ts @@ -8,7 +8,7 @@ import { getStorybookInfo, } from 'storybook/internal/common'; import type { PackageManagerName } from 'storybook/internal/common'; -import { frameworkToRenderer, getCoercedStorybookVersion } from 'storybook/internal/common'; +import { frameworkToRenderer } from 'storybook/internal/common'; import type { ConfigFile } from 'storybook/internal/csf-tools'; import { readConfig, writeConfig as writeConfigFile } from 'storybook/internal/csf-tools'; import { logger } from 'storybook/internal/node-logger'; @@ -101,11 +101,9 @@ export const getFrameworkOptions = ( export const getStorybookData = async ({ configDir: userDefinedConfigDir, - cwd, packageManagerName, }: { configDir?: string; - cwd?: string; packageManagerName?: PackageManagerName; cache?: boolean; }) => { @@ -115,7 +113,11 @@ export const getStorybookData = async ({ mainConfigPath: mainConfigPath, configDir: configDirFromScript, previewConfigPath, - } = await getStorybookInfo(userDefinedConfigDir, cwd); + versionSpecifier, + } = await getStorybookInfo( + userDefinedConfigDir, + userDefinedConfigDir ? dirname(userDefinedConfigDir) : undefined + ); const configDir = userDefinedConfigDir || configDirFromScript || '.storybook'; @@ -123,7 +125,7 @@ export const getStorybookData = async ({ const workingDir = isAbsolute(configDir) ? dirname(configDir) - : dirname(join(cwd ?? process.cwd(), configDir)); + : dirname(join(process.cwd(), configDir)); logger.debug('Getting stories paths...'); const storiesPaths = await getStoriesPathsFromConfig({ @@ -140,12 +142,15 @@ export const getStorybookData = async ({ }); logger.debug('Getting Storybook version...'); - const storybookVersion = await getCoercedStorybookVersion(packageManager); + const versionInstalled = (await packageManager.getModulePackageJSON('storybook'))?.version; return { configDir, mainConfig, - storybookVersion, + /** The version specifier of Storybook from the user's package.json */ + versionSpecifier, + /** The version of Storybook installed in the user's project */ + versionInstalled, mainConfigPath, previewConfigPath, packageManager, diff --git a/code/lib/cli-storybook/src/automigrate/index.test.ts b/code/lib/cli-storybook/src/automigrate/index.test.ts index 88b46248c5ea..e7e8f7553f9a 100644 --- a/code/lib/cli-storybook/src/automigrate/index.test.ts +++ b/code/lib/cli-storybook/src/automigrate/index.test.ts @@ -48,7 +48,7 @@ vi.mock('storybook/internal/node-logger', () => ({ }, })); -const fixes: Fix[] = [ +const fixes: Fix[] = [ { id: 'fix-1', @@ -88,7 +88,7 @@ class PackageManager implements Partial { } } -const packageManager = new PackageManager() as any as JsPackageManager; +const packageManager = new PackageManager() as unknown as JsPackageManager; const dryRun = false; const yes = true; @@ -113,17 +113,10 @@ const common = { storiesPaths: [], }; -const runFixWrapper = async ({ - beforeVersion, - storybookVersion, -}: { - beforeVersion: string; - storybookVersion: string; -}) => { +const runFixWrapper = async ({ storybookVersion }: { storybookVersion: string }) => { return runFixes({ ...common, storybookVersion, - beforeVersion, }); }; @@ -134,15 +127,13 @@ const runAutomigrateWrapper = async ({ beforeVersion: string; storybookVersion: string; }) => { - getStorybookData.mockImplementation(() => { - return { - ...common, - beforeVersion, - storybookVersion, - isLatest: true, - }; + getStorybookData.mockResolvedValue({ + ...common, + beforeVersion, + versionInstalled: storybookVersion, + isLatest: true, }); - return doAutomigrate({ configDir }); + return doAutomigrate({ configDir, fixes }); }; describe('runFixes', () => { @@ -161,7 +152,7 @@ describe('runFixes', () => { }); it('should be necessary to run fix-1 from SB 6.5.15 to 7.0.0', async () => { - const { fixResults } = await runFixWrapper({ beforeVersion, storybookVersion: '7.0.0' }); + const { fixResults } = await runFixWrapper({ storybookVersion: '7.0.0' }); expect(fixResults).toEqual({ 'fix-1': 'succeeded', @@ -182,7 +173,7 @@ describe('runFixes', () => { it('should fail if an error is thrown by migration', async () => { check1.mockRejectedValue(new Error('check1 error')); - const { fixResults } = await runFixWrapper({ beforeVersion, storybookVersion: '7.0.0' }); + const { fixResults } = await runFixWrapper({ storybookVersion: '7.0.0' }); expect(fixResults).toEqual({ 'fix-1': 'check_failed', @@ -190,7 +181,7 @@ describe('runFixes', () => { expect(run1).not.toHaveBeenCalled(); }); - it('should throw error if an error is thrown my migration', async () => { + it('should throw error if an error is thrown by migration', async () => { check1.mockRejectedValue(new Error('check1 error')); const result = runAutomigrateWrapper({ beforeVersion, storybookVersion: '7.0.0' }); diff --git a/code/lib/cli-storybook/src/automigrate/index.ts b/code/lib/cli-storybook/src/automigrate/index.ts index 937c2402ad3e..b2f6e0a74e21 100644 --- a/code/lib/cli-storybook/src/automigrate/index.ts +++ b/code/lib/cli-storybook/src/automigrate/index.ts @@ -46,7 +46,7 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { mainConfig, mainConfigPath, previewConfigPath, - storybookVersion, + versionInstalled, configDir, packageManager, storiesPaths, @@ -55,7 +55,7 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { packageManagerName: options.packageManager, }); - if (!storybookVersion) { + if (!versionInstalled) { throw new Error('Could not determine Storybook version'); } @@ -66,8 +66,7 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { const outcome = await automigrate({ ...options, packageManager, - storybookVersion, - beforeVersion: storybookVersion, + storybookVersion: versionInstalled, mainConfigPath, mainConfig, previewConfigPath, @@ -114,7 +113,6 @@ export const automigrate = async ({ mainConfigPath, previewConfigPath, storybookVersion, - beforeVersion, renderer: rendererPackage, skipInstall, hideMigrationSummary = false, @@ -184,7 +182,6 @@ export const automigrate = async ({ mainConfig, mainConfigPath, storybookVersion, - beforeVersion, isUpgrade: !!isUpgrade, dryRun, yes, @@ -219,7 +216,6 @@ type RunFixesOptions = { previewConfigPath?: string; mainConfig: StorybookConfigRaw; storybookVersion: string; - beforeVersion: string; isUpgrade?: boolean; }; diff --git a/code/lib/cli-storybook/src/automigrate/types.ts b/code/lib/cli-storybook/src/automigrate/types.ts index 627f810097ee..3a58893c1ed6 100644 --- a/code/lib/cli-storybook/src/automigrate/types.ts +++ b/code/lib/cli-storybook/src/automigrate/types.ts @@ -77,8 +77,6 @@ export interface AutofixOptions extends Omit { const results: DoctorCheckResult[] = []; diff --git a/code/lib/cli-storybook/src/doctor/types.ts b/code/lib/cli-storybook/src/doctor/types.ts index 677c7f2cef30..35854a0119b4 100644 --- a/code/lib/cli-storybook/src/doctor/types.ts +++ b/code/lib/cli-storybook/src/doctor/types.ts @@ -9,7 +9,7 @@ export interface DoctorOptions { export interface ProjectDoctorData { configDir: string; packageManager: JsPackageManager; - storybookVersion: string; + storybookVersion?: string; mainConfig: StorybookConfigRaw; } diff --git a/code/lib/cli-storybook/src/util.ts b/code/lib/cli-storybook/src/util.ts index a1009b5f056c..df825575a6c4 100644 --- a/code/lib/cli-storybook/src/util.ts +++ b/code/lib/cli-storybook/src/util.ts @@ -290,15 +290,15 @@ const processProject = async ({ packageManager, previewConfigPath, storiesPaths, - storybookVersion: beforeVersion, + versionInstalled, } = await getStorybookData({ configDir }); // Validate version and upgrade compatibility - logger.debug(`${name} - Validating before version... ${beforeVersion}`); - validateVersion(beforeVersion); - const isCanary = isCanaryVersion(currentCLIVersion) || isCanaryVersion(beforeVersion); + logger.debug(`${name} - Validating before version... ${versionInstalled}`); + validateVersion(versionInstalled); + const isCanary = isCanaryVersion(currentCLIVersion) || isCanaryVersion(versionInstalled); logger.debug(`${name} - Validating upgrade compatibility...`); - validateUpgradeCompatibility(currentCLIVersion, beforeVersion, isCanary); + validateUpgradeCompatibility(currentCLIVersion, versionInstalled, isCanary); // Get version information from NPM logger.debug(`${name} - Fetching NPM version information...`); @@ -312,7 +312,7 @@ const processProject = async ({ const isCLIExactLatest = currentCLIVersion === latestCLIVersionOnNPM; const isCLIPrerelease = prerelease(currentCLIVersion) !== null; const isCLIExactPrerelease = currentCLIVersion === latestPrereleaseCLIVersionOnNPM; - const isUpgrade = lt(beforeVersion, currentCLIVersion); + const isUpgrade = lt(versionInstalled, currentCLIVersion); // Check for blockers let autoblockerCheckResults: AutoblockerResult[] | null = null; @@ -341,7 +341,7 @@ const processProject = async ({ isCLIPrerelease, isCLIExactLatest, isUpgrade, - beforeVersion, + beforeVersion: versionInstalled, currentCLIVersion, latestCLIVersionOnNPM: latestCLIVersionOnNPM!, isCLIExactPrerelease,