diff --git a/code/addons/vitest/src/postinstall.ts b/code/addons/vitest/src/postinstall.ts index 731133213bb9..76a89d325f6f 100644 --- a/code/addons/vitest/src/postinstall.ts +++ b/code/addons/vitest/src/postinstall.ts @@ -24,7 +24,7 @@ import { SupportedFramework } from 'storybook/internal/types'; import * as find from 'empathic/find'; import { dirname, relative, resolve } from 'pathe'; -import { satisfies } from 'semver'; +import { coerce, satisfies } from 'semver'; import { dedent } from 'ts-dedent'; import { type PostinstallOptions } from '../../../lib/cli-storybook/src/add'; @@ -50,17 +50,33 @@ export default async function postInstall(options: PostinstallOptions) { { last: getProjectRoot(), cwd: options.configDir } ); - const vitestVersionSpecifier = await packageManager.getInstalledVersion('vitest'); + const allDeps = packageManager.getAllDependencies(); + + // Determine Vitest version/range from installed or declared dependency to avoid pulling + // incompatible majors by default. + let vitestVersionSpecifier = await packageManager.getInstalledVersion('vitest'); + if (!vitestVersionSpecifier && allDeps['vitest']) { + vitestVersionSpecifier = allDeps['vitest']; + } + + /** + * Coerce the version specifier to a version string + * + * This removed any version range specifiers like ^, ~, etc. which is needed to check with + * semver.satisfies. + */ + vitestVersionSpecifier = coerce(vitestVersionSpecifier)?.version ?? null; + logger.debug(`Vitest version specifier: ${vitestVersionSpecifier}`); const isVitest3_2To4 = vitestVersionSpecifier ? satisfies(vitestVersionSpecifier, '>=3.2.0 <4.0.0') : false; + const isVitest4OrNewer = vitestVersionSpecifier ? satisfies(vitestVersionSpecifier, '>=4.0.0') : true; const info = await getStorybookInfo(options.configDir); - const allDeps = packageManager.getAllDependencies(); // only install these dependencies if they are not already installed const addonVitestService = new AddonVitestService(packageManager); diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts index bd5bd4b542d6..4e49df4a86b1 100644 --- a/code/core/src/common/js-package-manager/JsPackageManager.ts +++ b/code/core/src/common/js-package-manager/JsPackageManager.ts @@ -631,6 +631,7 @@ export abstract class JsPackageManager { logger.debug(`Getting installed version for ${packageName}...`); const installations = await this.findInstallations([packageName]); if (!installations) { + logger.debug(`No installations found for ${packageName}`); // Cache the null result JsPackageManager.installedVersionCache.set(cacheKey, null); return null; @@ -646,6 +647,7 @@ export abstract class JsPackageManager { return coercedVersion; } catch (e) { + logger.error(`Error getting installed version for ${packageName}: ${String(e)}`); JsPackageManager.installedVersionCache.set(cacheKey, null); return null; } diff --git a/code/core/src/common/js-package-manager/NPMProxy.ts b/code/core/src/common/js-package-manager/NPMProxy.ts index 83d40eb46717..475b51eeb14d 100644 --- a/code/core/src/common/js-package-manager/NPMProxy.ts +++ b/code/core/src/common/js-package-manager/NPMProxy.ts @@ -144,7 +144,7 @@ export class NPMProxy extends JsPackageManager { const parsedOutput = JSON.parse(commandResult); return this.mapDependencies(parsedOutput, pattern); - } catch (e) { + } catch { // 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 { @@ -153,10 +153,8 @@ export class NPMProxy extends JsPackageManager { const parsedOutput = JSON.parse(commandResult); return this.mapDependencies(parsedOutput, pattern); - } catch (err) { - logger.debug( - `An issue occurred while trying to find dependencies metadata using npm: ${err}` - ); + } catch (e) { + logger.debug(`Error finding installations for ${pattern.join(', ')}: ${String(e)}`); return undefined; } } diff --git a/code/core/src/common/js-package-manager/PNPMProxy.ts b/code/core/src/common/js-package-manager/PNPMProxy.ts index b4c6119f0df8..7aba7c6d9e83 100644 --- a/code/core/src/common/js-package-manager/PNPMProxy.ts +++ b/code/core/src/common/js-package-manager/PNPMProxy.ts @@ -2,7 +2,7 @@ import { existsSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; import { pathToFileURL } from 'node:url'; -import { prompt } from 'storybook/internal/node-logger'; +import { logger, prompt } from 'storybook/internal/node-logger'; import { FindPackageVersionsError } from 'storybook/internal/server-errors'; import * as find from 'empathic/find'; @@ -113,9 +113,11 @@ export class PNPMProxy extends JsPackageManager { public async findInstallations(pattern: string[], { depth = 99 }: { depth?: number } = {}) { try { + const args = ['list', pattern.map((p) => `"${p}"`).join(' '), '--json', `--depth=${depth}`]; const childProcess = await executeCommand({ command: 'pnpm', - args: ['list', pattern.map((p) => `"${p}"`).join(' '), '--json', `--depth=${depth}`], + shell: true, + args, env: { FORCE_COLOR: 'false', }, @@ -126,6 +128,7 @@ export class PNPMProxy extends JsPackageManager { const parsedOutput = JSON.parse(commandResult); return this.mapDependencies(parsedOutput, pattern); } catch (e) { + logger.debug(`Error finding installations for ${pattern.join(', ')}: ${String(e)}`); return undefined; } } diff --git a/code/core/src/common/js-package-manager/Yarn1Proxy.ts b/code/core/src/common/js-package-manager/Yarn1Proxy.ts index 432b1a684d24..eb2f6218bd24 100644 --- a/code/core/src/common/js-package-manager/Yarn1Proxy.ts +++ b/code/core/src/common/js-package-manager/Yarn1Proxy.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs'; import { join } from 'node:path'; import process from 'node:process'; -import { prompt } from 'storybook/internal/node-logger'; +import { logger, prompt } from 'storybook/internal/node-logger'; import { FindPackageVersionsError } from 'storybook/internal/server-errors'; import * as find from 'empathic/find'; @@ -115,6 +115,7 @@ export class Yarn1Proxy extends JsPackageManager { const process = executeCommand({ command: 'yarn', args: yarnArgs.concat(pattern), + shell: true, env: { FORCE_COLOR: 'false', }, @@ -126,6 +127,7 @@ export class Yarn1Proxy extends JsPackageManager { const parsedOutput = JSON.parse(commandResult); return this.mapDependencies(parsedOutput, pattern); } catch (e) { + logger.debug(`Error finding installations for ${pattern.join(', ')}: ${String(e)}`); return undefined; } } diff --git a/code/core/src/common/js-package-manager/Yarn2Proxy.ts b/code/core/src/common/js-package-manager/Yarn2Proxy.ts index 71f09fedf3d7..6af73f4563c8 100644 --- a/code/core/src/common/js-package-manager/Yarn2Proxy.ts +++ b/code/core/src/common/js-package-manager/Yarn2Proxy.ts @@ -145,6 +145,7 @@ export class Yarn2Proxy extends JsPackageManager { return this.mapDependencies(commandResult, pattern); } catch (e) { + logger.debug(`Error finding installations for ${pattern.join(', ')}: ${String(e)}`); return undefined; } }