| 1 | // Sets one version on the root and every apps/* package.json, so a single tag names a release. Usage: bun scripts/bump-version.ts <major|minor|patch|x.y.z> |
| import { readdirSync, readFileSync, writeFileSync } from "node:fs"; |
| 3 |
| 4 | const SEMVER = /^(\d+)\.(\d+)\.(\d+)$/; |
| 5 | const VERSION_FIELD = /("version":\s*")[^"]*(")/; |
| 6 |
| 7 | export function nextVersion(current: string, bump: string) { |
| 8 | if (SEMVER.test(bump)) return bump; |
| 9 | const match = SEMVER.exec(current); |
| 10 | if (!match) throw new Error(`Root version "${current}" is not x.y.z`); |
| 11 | const [major, minor, patch] = match.slice(1).map(Number); |
| 12 | if (bump === "major") return `${major + 1}.0.0`; |
| 13 | if (bump === "minor") return `${major}.${minor + 1}.0`; |
| 14 | if (bump === "patch") return `${major}.${minor}.${patch + 1}`; |
| 15 | throw new Error(`Expected major, minor, patch or x.y.z, got "${bump}"`); |
| 16 | } |
| 17 |
| 18 | if (import.meta.main) { |
| 19 | process.chdir(`${import.meta.dir}/..`); |
| 20 |
| 21 | const files = [ |
| 22 | "package.json", |
| 23 | ...readdirSync("apps", { withFileTypes: true }) |
| 24 | .filter((entry) => entry.isDirectory()) |
| 25 | .map((entry) => `apps/${entry.name}/package.json`) |
| 26 | .filter((file) => { |
| 27 | try { |
| 28 | return VERSION_FIELD.test(readFileSync(file, "utf8")); |
| 29 | } catch { |
| 30 | return false; |
| 31 | } |
| 32 | }), |
| 33 | ]; |
| 34 |
| 35 | const current = JSON.parse(readFileSync("package.json", "utf8")).version; |
| 36 | const version = nextVersion(current, process.argv[2] ?? ""); |
| 37 |
| 38 | // a field edit rather than JSON.stringify, so each file keeps its own formatting |
| 39 | for (const file of files) { |
| 40 | writeFileSync( |
| 41 | file, |
| 42 | readFileSync(file, "utf8").replace(VERSION_FIELD, `$1${version}$2`), |
| 43 | ); |
| 44 | } |
| 45 |
| 46 | console.log( |
| 47 | `${current} -> ${version}\n${files.map((file) => ` ${file}`).join("\n")}`, |
| 48 | ); |
| 49 | console.log( |
| 50 | `Next: add a changelog entry, commit "release: ${version}", then tag v${version}.`, |
| 51 | ); |
| 52 | } |