import { readFileSync, write, writeFileSync } from "fs"; import { execSync } from "child_process"; import semver from "semver"; export function isGitAvailable() { try { execSync("git --version", { stdio: "ignore" }); return true; } catch (e) { return false; } } export function isGitRepo() { try { execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" }); return true; } catch (e) { return false; } } export function getGitVersion() { let rawGitVersion; let gitVersion; try { rawGitVersion = execSync("git describe --tags --dirty").toString().trim(); gitVersion = semver.coerce(rawGitVersion) || semver.coerce("0.0.0"); } catch (e) { return "0.0.0"; } // Git describe may return versions like v1.2.3-4-gabcdef // or v1.2.3-dirty or v1.2.3 or v1.2.3-4-gabcdef-dirty. // We need to return either a clean version or // append -dev for modified versions and // -dirty for dirty working tree. if (rawGitVersion.endsWith("-dirty")) { return gitVersion.version + "-dirty"; } else if (rawGitVersion.includes("-")) { return gitVersion.version + "-dev"; } else { return gitVersion.version || "0.0.0"; } } export function generateVersionFile(versionFilePath) { if (!isGitAvailable()) { throw new Error("Git is required to generate version info."); } // Read package.json version const packageVersion = JSON.parse( readFileSync("package.json", { encoding: "utf-8" }), ).version; let gitVersion = packageVersion; let gitBaseVersion = packageVersion; let isRelease = true; if (isGitRepo()) { // Get version from git repository gitVersion = getGitVersion(); gitBaseVersion = semver.coerce(gitVersion)?.version; // if git returned malformed version, throw error if (!gitBaseVersion || gitBaseVersion === "0.0.0") { throw new Error( "Cannot determine git version. Make sure the script is run in a git repository with tags.", ); } // Compare git version with package.json version if (semver.neq(gitBaseVersion, packageVersion)) { throw new Error( `Version mismatch: package.json version is ${packageVersion}, but git version is ${gitBaseVersion}`, ); } isRelease = gitVersion === packageVersion; } // Generate version file const buildDate = new Date().toISOString(); writeFileSync( versionFilePath, `// Auto-generated version file - do not edit manually // Generated at: ${buildDate} export const VERSION = '${packageVersion}'; export const IS_RELEASE = ${isRelease}; export const BUILD_TIME = '${buildDate}'; `, ); } if (import.meta.url === `file://${process.argv[1]}`) { generateVersionFile("src/version.js"); }