123 lines
4.8 KiB
JavaScript
123 lines
4.8 KiB
JavaScript
import { readFile, writeFile } from "node:fs/promises";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const frontendDir = fileURLToPath(new URL("../", import.meta.url));
|
|
const paths = {
|
|
packageJson: new URL("../package.json", import.meta.url),
|
|
packageLock: new URL("../package-lock.json", import.meta.url),
|
|
tauriConfig: new URL("../src-tauri/tauri.conf.json", import.meta.url),
|
|
cargoToml: new URL("../src-tauri/Cargo.toml", import.meta.url),
|
|
cargoLock: new URL("../src-tauri/Cargo.lock", import.meta.url),
|
|
};
|
|
const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
|
|
const readJson = async (path) => JSON.parse(await readFile(path, "utf8"));
|
|
const writeJson = async (path, value) => writeFile(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
|
|
const readCargoPackageVersion = async () => {
|
|
const cargo = await readFile(paths.cargoToml, "utf8");
|
|
const packageSection = cargo.match(/\[package\]([\s\S]*?)(?=\n\[|$)/)?.[1];
|
|
const version = packageSection?.match(/^version\s*=\s*"([^"]+)"/m)?.[1];
|
|
if (!version) throw new Error("Cannot find [package].version in src-tauri/Cargo.toml");
|
|
return version;
|
|
};
|
|
|
|
const readCargoLockPackageVersion = async () => {
|
|
const cargoLock = await readFile(paths.cargoLock, "utf8");
|
|
const packageSection = cargoLock
|
|
.match(/\[\[package\]\]([\s\S]*?)(?=\n\[\[package\]\]|$)/g)
|
|
?.find((section) => /^name\s*=\s*"ctms-desktop"$/m.test(section));
|
|
const version = packageSection?.match(/^version\s*=\s*"([^"]+)"/m)?.[1];
|
|
if (!version) throw new Error("Cannot find ctms-desktop version in src-tauri/Cargo.lock");
|
|
return version;
|
|
};
|
|
|
|
const readVersions = async () => {
|
|
const [packageJson, packageLock, tauriConfig, cargoVersion, cargoLockVersion] = await Promise.all([
|
|
readJson(paths.packageJson),
|
|
readJson(paths.packageLock),
|
|
readJson(paths.tauriConfig),
|
|
readCargoPackageVersion(),
|
|
readCargoLockPackageVersion(),
|
|
]);
|
|
return {
|
|
"package.json": packageJson.version,
|
|
"package-lock.json": packageLock.version,
|
|
"package-lock.json root": packageLock.packages?.[""]?.version,
|
|
"tauri.conf.json": tauriConfig.version,
|
|
"Cargo.toml": cargoVersion,
|
|
"Cargo.lock": cargoLockVersion,
|
|
};
|
|
};
|
|
|
|
const assertVersionsMatch = async () => {
|
|
const versions = await readVersions();
|
|
const uniqueVersions = new Set(Object.values(versions));
|
|
if (uniqueVersions.size !== 1 || uniqueVersions.has(undefined)) {
|
|
const details = Object.entries(versions)
|
|
.map(([file, version]) => ` ${file}: ${version ?? "<missing>"}`)
|
|
.join("\n");
|
|
throw new Error(`Client versions are not synchronized:\n${details}`);
|
|
}
|
|
const [version] = uniqueVersions;
|
|
console.log(`Client version ${version} is synchronized.`);
|
|
};
|
|
|
|
const setVersion = async (version) => {
|
|
if (!SEMVER_PATTERN.test(version)) {
|
|
throw new Error(`Invalid semantic version: ${version}`);
|
|
}
|
|
|
|
const [packageJson, packageLock, tauriConfig, tauriConfigSource, cargo, cargoLock] = await Promise.all([
|
|
readJson(paths.packageJson),
|
|
readJson(paths.packageLock),
|
|
readJson(paths.tauriConfig),
|
|
readFile(paths.tauriConfig, "utf8"),
|
|
readFile(paths.cargoToml, "utf8"),
|
|
readFile(paths.cargoLock, "utf8"),
|
|
]);
|
|
|
|
packageJson.version = version;
|
|
packageLock.version = version;
|
|
packageLock.packages[""].version = version;
|
|
|
|
const tauriVersionPattern = /("version"\s*:\s*")[^"]+(")/;
|
|
const packageSectionPattern = /(\[package\][\s\S]*?^version\s*=\s*")[^"]+(")/m;
|
|
const lockPackagePattern =
|
|
/(\[\[package\]\]\nname\s*=\s*"ctms-desktop"\nversion\s*=\s*")[^"]+(")/m;
|
|
if (typeof tauriConfig.version !== "string" || !tauriVersionPattern.test(tauriConfigSource)) {
|
|
throw new Error("Cannot update version in src-tauri/tauri.conf.json");
|
|
}
|
|
if (!packageSectionPattern.test(cargo)) {
|
|
throw new Error("Cannot update [package].version in src-tauri/Cargo.toml");
|
|
}
|
|
if (!lockPackagePattern.test(cargoLock)) {
|
|
throw new Error("Cannot update ctms-desktop version in src-tauri/Cargo.lock");
|
|
}
|
|
|
|
await Promise.all([
|
|
writeJson(paths.packageJson, packageJson),
|
|
writeJson(paths.packageLock, packageLock),
|
|
writeFile(paths.tauriConfig, tauriConfigSource.replace(tauriVersionPattern, `$1${version}$2`)),
|
|
writeFile(paths.cargoToml, cargo.replace(packageSectionPattern, `$1${version}$2`)),
|
|
writeFile(paths.cargoLock, cargoLock.replace(lockPackagePattern, `$1${version}$2`)),
|
|
]);
|
|
console.log(`Updated CTMS Web and Desktop client version to ${version} in ${frontendDir}`);
|
|
await assertVersionsMatch();
|
|
};
|
|
|
|
const [, , command = "--check", value] = process.argv;
|
|
|
|
try {
|
|
if (command === "--check") {
|
|
await assertVersionsMatch();
|
|
} else if (command === "--set" && value) {
|
|
await setVersion(value);
|
|
} else {
|
|
throw new Error("Usage: node scripts/client-version.mjs [--check | --set <semver>]");
|
|
}
|
|
} catch (error) {
|
|
console.error(error instanceof Error ? error.message : error);
|
|
process.exitCode = 1;
|
|
}
|