diff --git a/packages/cli/src/version.ts b/packages/cli/src/version.ts index 5b31122f4e..3cf22a4b76 100644 --- a/packages/cli/src/version.ts +++ b/packages/cli/src/version.ts @@ -1,21 +1,23 @@ import fs from 'node:fs'; -import { createRequire } from 'node:module'; import path from 'node:path'; import { vitePlusHeader } from '../binding/index.js'; +import cliPkg from '../package.json' with { type: 'json' }; import { VITE_PLUS_NAME } from './utils/constants.js'; import { renderCliDoc } from './utils/help.js'; import { detectPackageMetadata, hasVitePlusDependency } from './utils/package.js'; import { accent, log } from './utils/terminal.js'; -const require = createRequire(import.meta.url); - -interface PackageJson { - version?: string; - bundledVersions?: Record; - dependencies?: Record; - devDependencies?: Record; -} +/** Tool display names in the order shown by `vp --version`. */ +const TOOL_DISPLAY_ORDER = [ + 'vite', + 'rolldown', + 'vitest', + 'oxfmt', + 'oxlint', + 'oxlint-tsgolint', + 'tsdown', +] as const; interface LocalPackageMetadata { name: string; @@ -23,20 +25,12 @@ interface LocalPackageMetadata { path: string; } -interface ToolVersionSpec { - displayName: string; - packageName: string; - bundledVersionKey?: string; - fallbackPackageJson?: string; -} - function getGlobalVersion(): string | null { return process.env.VP_GLOBAL_VERSION ?? null; } function getCliVersion(): string | null { - const pkg = resolvePackageJson(VITE_PLUS_NAME, process.cwd()); - return pkg?.version ?? null; + return cliPkg.version ?? null; } function getLocalMetadata(cwd: string): LocalPackageMetadata | null { @@ -50,9 +44,13 @@ function isVitePlusDeclaredInAncestors(cwd: string): boolean { let currentDir = path.resolve(cwd); while (true) { const packageJsonPath = path.join(currentDir, 'package.json'); - const pkg = readPackageJsonFromPath(packageJsonPath); - if (pkg && hasVitePlusDependency(pkg)) { - return true; + try { + const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); + if (hasVitePlusDependency(pkg)) { + return true; + } + } catch { + // no package.json at this level } const parentDir = path.dirname(currentDir); if (parentDir === currentDir) { @@ -63,60 +61,20 @@ function isVitePlusDeclaredInAncestors(cwd: string): boolean { return false; } -function readPackageJsonFromPath(packageJsonPath: string): PackageJson | null { - try { - return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as PackageJson; - } catch { - return null; - } -} - -function resolvePackageJson(packageName: string, baseDir: string): PackageJson | null { +/** + * Resolve all tool versions from the locally installed vite-plus package. + * Uses the `vite-plus/versions` export generated by `syncVersionsExport()`. + */ +async function resolveToolVersions(localPackagePath: string): Promise> { try { - // Try resolving package.json subpath directly - const packageJsonPath = require.resolve(`${packageName}/package.json`, { - paths: [baseDir], - }); - return readPackageJsonFromPath(packageJsonPath); - } catch { - // Fallback for packages with restricted exports that don't expose ./package.json: - // resolve the main entry and find package.json relative to it - try { - const mainPath = require.resolve(packageName, { paths: [baseDir] }); - // Walk up from the resolved entry to find the package.json - let dir = path.dirname(mainPath); - while (dir !== path.dirname(dir)) { - const pkgPath = path.join(dir, 'package.json'); - const pkg = readPackageJsonFromPath(pkgPath); - if (pkg) { - return pkg; - } - dir = path.dirname(dir); - } - } catch { - // package not found at all + const mod = await import(`${localPackagePath}/dist/versions.js`); + if (mod.versions && typeof mod.versions === 'object') { + return mod.versions as Record; } - return null; - } -} - -function resolveToolVersion(tool: ToolVersionSpec, localPackagePath: string): string | null { - const pkg = resolvePackageJson(tool.packageName, localPackagePath); - const bundledVersion = tool.bundledVersionKey - ? (pkg?.bundledVersions?.[tool.bundledVersionKey] ?? null) - : null; - if (bundledVersion) { - return bundledVersion; - } - const version = pkg?.version ?? null; - if (version) { - return version; - } - if (tool.fallbackPackageJson) { - const fallbackPath = path.join(localPackagePath, tool.fallbackPackageJson); - return readPackageJsonFromPath(fallbackPath)?.version ?? null; + } catch { + // versions module not available } - return null; + return {}; } /** @@ -145,52 +103,14 @@ export async function printVersion(cwd: string) { }, ]; - const tools: ToolVersionSpec[] = [ - { - displayName: 'vite', - packageName: '@voidzero-dev/vite-plus-core', - bundledVersionKey: 'vite', - }, - { - displayName: 'rolldown', - packageName: '@voidzero-dev/vite-plus-core', - bundledVersionKey: 'rolldown', - }, - { - displayName: 'vitest', - packageName: '@voidzero-dev/vite-plus-test', - bundledVersionKey: 'vitest', - }, - { - displayName: 'oxfmt', - packageName: 'oxfmt', - }, - { - displayName: 'oxlint', - packageName: 'oxlint', - }, - { - displayName: 'oxlint-tsgolint', - packageName: 'oxlint-tsgolint', - }, - { - displayName: 'tsdown', - packageName: '@voidzero-dev/vite-plus-core', - bundledVersionKey: 'tsdown', - }, - ]; - if (localMetadata) { - const resolvedTools = tools.map((tool) => ({ - tool, - version: resolveToolVersion(tool, localMetadata.path), - })); + const versions = await resolveToolVersions(localMetadata.path); sections.push({ title: 'Tools', - rows: resolvedTools.map(({ tool, version }) => ({ - label: accent(tool.displayName), - description: version ? `v${version}` : 'Not found', + rows: TOOL_DISPLAY_ORDER.map((name) => ({ + label: accent(name), + description: versions[name] ? `v${versions[name]}` : 'Not found', })), }); }