Skip to content

Commit 9181652

Browse files
feat(releases): bring back the Latest and Maintenance badges, correctly sort releases
1 parent 45c5df5 commit 9181652

File tree

3 files changed

+63
-22
lines changed

3 files changed

+63
-22
lines changed

src/routes/package/[...package]/+page.server.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import semver from "semver";
21
import { error } from "@sveltejs/kit";
2+
import semver from "semver";
33
import { gitHubCache, type GitHubRelease } from "$lib/server/github-cache";
44
import { discoverer } from "$lib/server/package-discoverer";
55
import type { Repository } from "$lib/repositories";
@@ -13,7 +13,7 @@ export async function load({ params }) {
1313
Pick<(typeof categorizedPackages)[number]["packages"][number], "pkg">)
1414
| undefined = undefined;
1515
const foundVersions = new Set<string>();
16-
const releases: (GitHubRelease & { cleanVersion: string })[] = [];
16+
const releases: ({ cleanName: string; cleanVersion: string } & GitHubRelease)[] = [];
1717

1818
// Discover releases
1919
console.log("Starting loading releases...");
@@ -48,15 +48,15 @@ export async function load({ params }) {
4848
// 3. For each release, check if it is already found, searching by versions
4949
const { dataFilter, metadataFromTag, changelogContentsReplacer, ...rest } = repo;
5050
for (const release of validReleases) {
51-
const [, cleanVersion] = repo.metadataFromTag(release.tag_name);
51+
const [cleanName, cleanVersion] = repo.metadataFromTag(release.tag_name);
5252
console.log(`Release ${release.tag_name}, extracted version: ${cleanVersion}`);
5353
if (foundVersions.has(cleanVersion)) continue;
5454

5555
// If not, add its version to the set and itself to the final version
5656
const currentNewestVersion = [...foundVersions].sort(semver.rcompare)[0];
5757
console.log("Current newest version", currentNewestVersion);
5858
foundVersions.add(cleanVersion);
59-
releases.push({ ...release, cleanVersion });
59+
releases.push({ cleanName, cleanVersion, ...release });
6060

6161
// If it is newer than the newest we got, set this repo as the "final repo"
6262
if (!currentNewestVersion || semver.gt(cleanVersion, currentNewestVersion)) {
@@ -79,9 +79,11 @@ export async function load({ params }) {
7979
// Return the final sorted results and filter back out the clean version
8080
return {
8181
currentPackage,
82-
releases: releases
83-
.toSorted((a, b) => semver.rcompare(a.cleanVersion, b.cleanVersion))
84-
.filter(({ cleanVersion, ...release }) => release)
82+
releases: releases.toSorted(
83+
(a, b) =>
84+
new Date(b.published_at ?? b.created_at).getTime() -
85+
new Date(a.published_at ?? a.created_at).getTime()
86+
)
8587
};
8688
}
8789

src/routes/package/[...package]/+page.svelte

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
<script lang="ts">
22
import { navigating } from "$app/state";
33
import { LoaderCircle } from "@lucide/svelte";
4+
import semver from "semver";
45
import ReleaseCard from "./ReleaseCard.svelte";
56
import SidePanel from "./SidePanel.svelte";
67
import * as Accordion from "$lib/components/ui/accordion";
78
import { Skeleton } from "$lib/components/ui/skeleton";
89
910
let { data } = $props();
11+
let latestRelease = $derived(
12+
data.releases.toSorted((a, b) => semver.rcompare(a.cleanVersion, b.cleanVersion))[0]
13+
);
14+
let earliestOfLatestMajor = $derived(
15+
data.releases
16+
.filter(
17+
({ prerelease, cleanVersion }) =>
18+
(latestRelease
19+
? semver.major(cleanVersion) === semver.major(latestRelease.cleanVersion)
20+
: false) && !prerelease
21+
)
22+
.sort((a, b) => semver.compare(a.cleanVersion, b.cleanVersion))[0]
23+
);
1024
</script>
1125

1226
{#snippet loading()}
@@ -58,11 +72,29 @@
5872
.map(({ id }) => id.toString())}
5973
class="w-full"
6074
>
61-
{#each data.releases as release (release.id)}
75+
{#each data.releases as release, index (release.id)}
76+
{@const semVersion = semver.coerce(release.cleanVersion)}
77+
{@const isMajorRelease =
78+
!release.prerelease &&
79+
semVersion?.minor === 0 &&
80+
semVersion?.patch === 0 &&
81+
!semVersion?.prerelease.length}
82+
{@const releaseDate = new Date(release.published_at ?? release.created_at)}
83+
{@const isLatest = release.id === latestRelease?.id}
84+
{@const isMaintenance = earliestOfLatestMajor
85+
? !isMajorRelease &&
86+
/* `semVersion` and `latestRelease` can't be undefined here */
87+
semVersion!.major < semver.major(latestRelease!.cleanVersion) &&
88+
releaseDate >
89+
new Date(earliestOfLatestMajor.published_at ?? earliestOfLatestMajor.created_at)
90+
: false}
6291
<ReleaseCard
92+
{index}
6393
packageName={data.currentPackage.pkg.name}
6494
repo={{ owner: data.currentPackage.owner, name: data.currentPackage.repoName }}
6595
{release}
96+
{isLatest}
97+
{isMaintenance}
6698
/>
6799
{/each}
68100
</Accordion.Root>

src/routes/package/[...package]/ReleaseCard.svelte

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,27 @@
1111
import ListElementRenderer from "$lib/components/renderers/ListElementRenderer.svelte";
1212
1313
type Props = {
14+
index?: number;
1415
packageName: string;
1516
repo: {
1617
owner: string;
1718
name: string;
1819
};
19-
release: GitHubRelease;
20+
release: { cleanName: string; cleanVersion: string } & GitHubRelease;
21+
isLatest?: boolean;
22+
isMaintenance?: boolean;
2023
};
21-
let { packageName, repo, release }: Props = $props();
24+
let {
25+
index = 0,
26+
packageName,
27+
repo,
28+
release,
29+
isLatest: isLatestRelease = false,
30+
isMaintenance: isMaintenanceRelease = false
31+
}: Props = $props();
2232
23-
let releaseVersion = $derived.by(() => {
24-
let tag = release.tag_name;
25-
if (tag.includes("@")) tag = tag.substring(tag.lastIndexOf("@"));
26-
return semver.coerce(tag.replace(/^v/, ""));
27-
});
33+
let releaseVersion = $derived(release.cleanVersion);
34+
let semVersion = $derived(semver.coerce(releaseVersion));
2835
let releaseDate = $derived(new Date(release.published_at ?? release.created_at));
2936
let releaseBody = $derived.by(() => {
3037
if (!release.body) return "_No release body_";
@@ -40,16 +47,16 @@
4047
}
4148
);
4249
});
43-
let isMajorRelease = $derived(release.tag_name.includes(".0.0") && !release.prerelease);
50+
let isMajorRelease = $derived(
51+
!release.prerelease &&
52+
semVersion?.minor === 0 &&
53+
semVersion?.patch === 0 &&
54+
!semVersion?.prerelease.length
55+
);
4456
let isOlderThanAWeek = $derived(
4557
releaseDate.getTime() < new Date().getTime() - 1000 * 60 * 60 * 24 * 7
4658
);
4759
48-
// TODO: figure this out
49-
let index = 0;
50-
let isLatestRelease = false;
51-
let isMaintenanceRelease = false;
52-
5360
/**
5461
* Converts a date to a relative date string.
5562
* e.g., "2 days ago", "3 hours ago", "1 minute ago"
@@ -152,7 +159,7 @@
152159
</Tooltip.Trigger>
153160
<Tooltip.Content>
154161
{packageName}
155-
{releaseVersion?.major} is available!
162+
{semVersion?.major} is available!
156163
</Tooltip.Content>
157164
</Tooltip.Root>
158165
</Tooltip.Provider>

0 commit comments

Comments
 (0)