Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions nodejs/scripts/calculate-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as semver from "semver";

const validCommands = ["current", "current-prerelease", "latest", "prerelease", "unstable"];

export function calculateVersion(command, { latest, prerelease, unstable }) {
if (!validCommands.includes(command)) {
throw new Error(
`Invalid argument, must be one of: ${validCommands.join(", ")}, got: "${command}"`
);
}

if (!latest) {
throw new Error("No latest version found. Publish an initial version first.");
}

// Output the current latest version to stdout
if (command === "current") {
return latest;
}
Comment on lines +6 to +19

// Use latest if no prerelease exists, or compare to find higher
let higherVersion;
if (!prerelease) {
higherVersion = latest;
} else {
try {
higherVersion = semver.gt(latest, prerelease) ? latest : prerelease;
} catch (err) {
throw new Error(
`Failed to compare versions "${latest}" and "${prerelease}": ${err.message}`
);
}
}

// Output the most recent version including prerelease versions to stdout
if (command === "current-prerelease") {
return higherVersion;
}

if (command === "unstable") {
if (unstable && semver.gt(unstable, higherVersion)) {
higherVersion = unstable;
}
}

const increment = command === "latest" ? "patch" : "prerelease";
const isIncrementingExistingPrerelease = semver.prerelease(higherVersion) !== null;
const prereleaseIdentifier =
command === "prerelease"
? isIncrementingExistingPrerelease
? undefined
: "preview"
: command === "unstable"
? "unstable"
: undefined;
const nextVersion = semver.inc(higherVersion, increment, prereleaseIdentifier);
if (!nextVersion) {
throw new Error(`Failed to increment version "${higherVersion}" with "${increment}"`);
}

return nextVersion;
}
72 changes: 6 additions & 66 deletions nodejs/scripts/get-version.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
import { execSync } from "child_process";
import * as semver from "semver";
import { calculateVersion } from "./calculate-version.js";

async function getLatestVersion(tag) {
try {
Expand All @@ -30,69 +31,8 @@ async function getLatestVersion(tag) {
}
}

async function main() {
const command = process.argv[2];
const validCommands = ["current", "current-prerelease", "latest", "prerelease", "unstable"];
if (!validCommands.includes(command)) {
console.error(
`Invalid argument, must be one of: ${validCommands.join(", ")}, got: "${command}"`
);
process.exit(1);
}

const latest = await getLatestVersion("latest");
if (!latest) {
console.error("No latest version found. Publish an initial version first.");
process.exit(1);
}

// Output the current latest version to stdout
if (command === "current") {
console.log(latest);
return;
}

const prerelease = await getLatestVersion("prerelease");

// Use latest if no prerelease exists, or compare to find higher
let higherVersion;
if (!prerelease) {
higherVersion = latest;
} else {
try {
higherVersion = semver.gt(latest, prerelease) ? latest : prerelease;
} catch (err) {
console.error(
`Failed to compare versions "${latest}" and "${prerelease}": ${err.message}`
);
process.exit(1);
}
}

// Output the most recent version including prerelease versions to stdout
if (command === "current-prerelease") {
console.log(higherVersion);
return;
}

if (command === "unstable") {
const unstable = await getLatestVersion("unstable");
if (unstable && semver.gt(unstable, higherVersion)) {
higherVersion = unstable;
}
}

const increment = command === "latest" ? "patch" : "prerelease";
const prereleaseIdentifier =
command === "prerelease" ? "preview" : command === "unstable" ? "unstable" : undefined;
const nextVersion = semver.inc(higherVersion, increment, prereleaseIdentifier);
if (!nextVersion) {
console.error(`Failed to increment version "${higherVersion}" with "${increment}"`);
process.exit(1);
}

// Output the next version to stdout
console.log(nextVersion);
}

void main();
const command = process.argv[2];
const latest = await getLatestVersion("latest");
const prerelease = await getLatestVersion("prerelease");
const unstable = command === "unstable" ? await getLatestVersion("unstable") : undefined;
Comment on lines +35 to +37
console.log(calculateVersion(command, { latest, prerelease, unstable }));
Comment on lines +34 to +38
40 changes: 40 additions & 0 deletions nodejs/test/get-version.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { describe, expect, it } from "vitest";
import { calculateVersion } from "../scripts/calculate-version.js";

describe("get-version", () => {
it("increments stable latest versions by patch", () => {
expect(calculateVersion("latest", { latest: "1.0.1" })).toBe("1.0.2");
});

it("promotes a higher prerelease to stable for latest releases", () => {
expect(calculateVersion("latest", { latest: "0.3.0", prerelease: "1.0.0-beta.1" })).toBe(
"1.0.0"
);
});

it("starts preview prereleases when incrementing from a stable release", () => {
expect(calculateVersion("prerelease", { latest: "0.3.0" })).toBe("0.3.1-preview.0");
});

it("preserves custom prerelease identifiers when incrementing prereleases", () => {
expect(
calculateVersion("prerelease", { latest: "0.3.0", prerelease: "0.4.0-chicken.2" })
).toBe("0.4.0-chicken.3");
});

it("preserves beta prerelease identifiers when incrementing prereleases", () => {
expect(
calculateVersion("prerelease", { latest: "0.3.0", prerelease: "1.0.0-beta.1" })
).toBe("1.0.0-beta.2");
});

it("increments unstable releases with the unstable identifier", () => {
expect(
calculateVersion("unstable", {
latest: "0.3.0",
prerelease: "0.4.0-chicken.2",
unstable: "0.5.0-unstable.2",
})
).toBe("0.5.0-unstable.3");
});
});
Loading