diff --git a/src/commands/versions.ts b/src/commands/versions.ts index 97c2ac4..8c67a79 100644 --- a/src/commands/versions.ts +++ b/src/commands/versions.ts @@ -1,6 +1,17 @@ import { defineCommand } from "citty"; import consola from "consola"; +import type { Version } from "../core/types.ts"; + import { sharedArgs, resolvePURL, withErrorHandling } from "./shared.ts"; +export function selectRecentVersions(versions: Version[], limit: number): Version[] { + return versions + .toSorted((a, b) => { + if (a.publishedAt === null) return b.publishedAt === null ? 0 : 1; + if (b.publishedAt === null) return -1; + return b.publishedAt.getTime() - a.publishedAt.getTime(); + }) + .slice(0, limit); +} export default defineCommand({ meta: { @@ -26,14 +37,13 @@ export default defineCommand({ const [reg, name] = resolvePURL(args.purl, !args["no-cache"]); const versions = await reg.fetchVersions(name); const limit = Number.parseInt(args.limit, 10) || 20; + const shown = selectRecentVersions(versions, limit); if (args.json) { - console.log(JSON.stringify(versions.slice(0, limit), null, 2)); + console.log(JSON.stringify(shown, null, 2)); return; } - const shown = versions.slice(0, limit); - consola.log(""); consola.log( ` \x1b[1m${name}\x1b[0m — ${versions.length} version${versions.length === 1 ? "" : "s"}`, diff --git a/test/unit/versions-command.test.ts b/test/unit/versions-command.test.ts new file mode 100644 index 0000000..b55c4d0 --- /dev/null +++ b/test/unit/versions-command.test.ts @@ -0,0 +1,45 @@ +import type { Version } from "../../src/core/types.ts"; +import { selectRecentVersions } from "../../src/commands/versions.ts"; + +function createVersion(number: string, publishedAt: string | null): Version { + return { + number, + publishedAt: publishedAt ? new Date(publishedAt) : null, + licenses: "", + integrity: "", + status: "", + metadata: {}, + }; +} + +describe("selectRecentVersions", () => { + it("limits versions after sorting by recency and keeps undated versions last", () => { + const versions = [ + createVersion("1.0.0", "2022-01-01T00:00:00Z"), + createVersion("unknown-a", null), + createVersion("3.0.0", "2024-01-01T00:00:00Z"), + createVersion("2.0.0", "2023-01-01T00:00:00Z"), + createVersion("unknown-b", null), + ]; + + expect(selectRecentVersions(versions, 3).map(({ number }) => number)).toEqual([ + "3.0.0", + "2.0.0", + "1.0.0", + ]); + expect(selectRecentVersions(versions, 5).map(({ number }) => number)).toEqual([ + "3.0.0", + "2.0.0", + "1.0.0", + "unknown-a", + "unknown-b", + ]); + expect(versions.map(({ number }) => number)).toEqual([ + "1.0.0", + "unknown-a", + "3.0.0", + "2.0.0", + "unknown-b", + ]); + }); +});