Files
Rune-Spec/scripts/release.ts

98 lines
3.0 KiB
TypeScript

import { readFileSync, writeFileSync } from "node:fs";
import { createInterface } from "node:readline";
import { join } from "node:path";
interface Semver {
major: number;
minor: number;
patch: number;
}
type BumpType = "major" | "minor" | "patch";
export function parseSemver(version: string): Semver {
const parts = version.split(".");
if (parts.length !== 3) {
throw new Error(`无效的版本号格式: ${version}`);
}
const [major, minor, patch] = parts.map((p) => {
const n = Number(p);
if (Number.isNaN(n) || !Number.isInteger(n) || n < 0) {
throw new Error(`无效的版本号格式: ${version}`);
}
return n;
});
return { major: major!, minor: minor!, patch: patch! };
}
export function bumpVersion(current: string, type: BumpType): string {
const semver = parseSemver(current);
switch (type) {
case "major":
return `${semver.major + 1}.0.0`;
case "minor":
return `${semver.major}.${semver.minor + 1}.0`;
case "patch":
return `${semver.major}.${semver.minor}.${semver.patch + 1}`;
}
}
async function ask(query: string): Promise<string> {
const rl = createInterface({ input: process.stdin, output: process.stdout });
return new Promise((resolve) => {
rl.question(query, (answer) => {
rl.close();
resolve(answer.trim());
});
});
}
async function selectBumpType(): Promise<BumpType> {
console.log("选择版本递增类型:");
console.log(" 1) major - 不兼容的 API 变更");
console.log(" 2) minor - 向下兼容的功能新增");
console.log(" 3) patch - 向下兼容的问题修正");
while (true) {
const answer = await ask("请输入 1/2/3 [3]: ");
const choice = answer || "3";
if (choice === "1") return "major";
if (choice === "2") return "minor";
if (choice === "3") return "patch";
console.log("无效选择,请输入 1、2 或 3");
}
}
async function stepBumpVersion(): Promise<string> {
const pkgPath = join(import.meta.dir, "..", "package.json");
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")) as { version: string };
if (typeof pkg.version !== "string" || pkg.version.length === 0) {
throw new Error("package.json 中缺少有效的 version 字段");
}
const currentVersion = pkg.version;
const bumpType = await selectBumpType();
const newVersion = bumpVersion(currentVersion, bumpType);
const answer = await ask(`确认版本号 ${currentVersion}${newVersion}? [y/N]: `);
if (answer.toLowerCase() !== "y") {
console.log("已取消");
process.exit(0);
}
pkg.version = newVersion;
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
console.log(`版本号已更新: ${currentVersion}${newVersion}`);
return newVersion;
}
async function main(): Promise<void> {
const newVersion = await stepBumpVersion();
console.log(`[1/4] 版本号递增完成: ${newVersion}`);
}
main().catch((err: unknown) => {
console.error(err instanceof Error ? err.message : String(err));
process.exit(1);
});