import fs from "fs/promises"; import path from "path"; import { program } from "commander"; /** * 验证版本号格式 * @param {string} version * @returns {boolean} */ function isValidVersion(version) { return /^v?\d+\.\d+\.\d+(-(alpha|beta|rc)(\.\d+)?)?$/i.test(version); } /** * 标准化版本号(确保v前缀可选) * @param {string} version * @returns {string} */ function normalizeVersion(version) { return version.startsWith("v") ? version : `v${version}`; } /** * 更新 package.json 文件中的版本号 * @param {string} newVersion 新版本号 */ async function updatePackageVersion(newVersion) { const _dirname = process.cwd(); const packageJsonPath = path.join(_dirname, "package.json"); try { const data = await fs.readFile(packageJsonPath, "utf8"); const packageJson = JSON.parse(data); console.log( "[INFO]: Current package.json version is: ", packageJson.version, ); packageJson.version = newVersion.startsWith("v") ? newVersion.slice(1) : newVersion; await fs.writeFile( packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8", ); console.log( `[INFO]: package.json version updated to: ${packageJson.version}`, ); return packageJson.version; } catch (error) { console.error("Error updating package.json version:", error); throw error; } } /** * 更新 Cargo.toml 文件中的版本号 * @param {string} newVersion 新版本号 */ async function updateCargoVersion(newVersion) { const _dirname = process.cwd(); const cargoTomlPath = path.join(_dirname, "src-tauri", "Cargo.toml"); try { const data = await fs.readFile(cargoTomlPath, "utf8"); const lines = data.split("\n"); const versionWithoutV = newVersion.startsWith("v") ? newVersion.slice(1) : newVersion; const updatedLines = lines.map((line) => { if (line.trim().startsWith("version =")) { return line.replace( /version\s*=\s*"[^"]+"/, `version = "${versionWithoutV}"`, ); } return line; }); await fs.writeFile(cargoTomlPath, updatedLines.join("\n"), "utf8"); console.log(`[INFO]: Cargo.toml version updated to: ${versionWithoutV}`); } catch (error) { console.error("Error updating Cargo.toml version:", error); throw error; } } /** * 更新 tauri.conf.json 文件中的版本号 * @param {string} newVersion 新版本号 */ async function updateTauriConfigVersion(newVersion) { const _dirname = process.cwd(); const tauriConfigPath = path.join(_dirname, "src-tauri", "tauri.conf.json"); try { const data = await fs.readFile(tauriConfigPath, "utf8"); const tauriConfig = JSON.parse(data); const versionWithoutV = newVersion.startsWith("v") ? newVersion.slice(1) : newVersion; console.log( "[INFO]: Current tauri.conf.json version is: ", tauriConfig.version, ); tauriConfig.version = versionWithoutV; await fs.writeFile( tauriConfigPath, JSON.stringify(tauriConfig, null, 2), "utf8", ); console.log( `[INFO]: tauri.conf.json version updated to: ${versionWithoutV}`, ); } catch (error) { console.error("Error updating tauri.conf.json version:", error); throw error; } } /** * 获取当前版本号(从package.json) */ async function getCurrentVersion() { const _dirname = process.cwd(); const packageJsonPath = path.join(_dirname, "package.json"); try { const data = await fs.readFile(packageJsonPath, "utf8"); const packageJson = JSON.parse(data); return packageJson.version; } catch (error) { console.error("Error getting current version:", error); throw error; } } /** * 主函数,更新所有文件的版本号 * @param {string} versionArg 版本参数(可以是标签或完整版本号) */ async function main(versionArg) { if (!versionArg) { console.error("Error: Version argument is required"); process.exit(1); } try { let newVersion; const validTags = ["alpha", "beta", "rc"]; // 判断参数是标签还是完整版本号 if (validTags.includes(versionArg.toLowerCase())) { // 标签模式:在当前版本基础上添加标签 const currentVersion = await getCurrentVersion(); const baseVersion = currentVersion.replace( /-(alpha|beta|rc)(\.\d+)?$/i, "", ); newVersion = `${baseVersion}-${versionArg.toLowerCase()}`; } else { // 完整版本号模式 if (!isValidVersion(versionArg)) { console.error( "Error: Invalid version format. Expected format: vX.X.X or vX.X.X-tag (e.g. v2.2.3 or v2.2.3-alpha)", ); process.exit(1); } newVersion = normalizeVersion(versionArg); } console.log(`[INFO]: Updating versions to: ${newVersion}`); await updatePackageVersion("v" + newVersion); await updateCargoVersion(newVersion); await updateTauriConfigVersion(newVersion); console.log("[SUCCESS]: All version updates completed successfully!"); } catch (error) { console.error("[ERROR]: Failed to update versions:", error); process.exit(1); } } // 设置命令行界面 program .name("pnpm release-version") .description( "Update project version numbers. Can add tag (alpha/beta/rc) or set full version (e.g. v2.2.3 or v2.2.3-alpha)", ) .argument( "", "version tag (alpha/beta/rc) or full version (e.g. v2.2.3 or v2.2.3-alpha)", ) .action(main) .parse(process.argv);