| 1 | const REPO = "pingdotgg/t3code"; |
| 2 | |
| 3 | export const RELEASES_URL = `https://github.com/${REPO}/releases`; |
| 4 | export const NIGHTLY_RELEASES_URL = `${RELEASES_URL}?q=nightly&expanded=true`; |
| 5 | |
| 6 | const LATEST_API_URL = `https://api.github.com/repos/${REPO}/releases/latest`; |
| 7 | // The `latest` endpoint skips prereleases, so nightly needs the list. GitHub |
| 8 | // returns it newest first and nightlies land several times a day, so the first |
| 9 | // nightly tag in a small page is the current build. |
| 10 | const LIST_API_URL = `https://api.github.com/repos/${REPO}/releases?per_page=10`; |
| 11 | |
| 12 | export type ReleaseChannel = "stable" | "nightly"; |
| 13 | |
| 14 | export interface ReleaseAsset { |
| 15 | name: string; |
| 16 | browser_download_url: string; |
| 17 | } |
| 18 | |
| 19 | export interface Release { |
| 20 | tag_name: string; |
| 21 | html_url: string; |
| 22 | published_at: string; |
| 23 | assets: ReleaseAsset[]; |
| 24 | } |
| 25 | |
| 26 | function cacheKey(channel: ReleaseChannel) { |
| 27 | return `t3code-${channel}-release`; |
| 28 | } |
| 29 | |
| 30 | async function fetchStable(): Promise<Release> { |
| 31 | return fetch(LATEST_API_URL).then((r) => r.json()); |
| 32 | } |
| 33 | |
| 34 | async function fetchNightly(): Promise<Release> { |
| 35 | const list: Release[] = await fetch(LIST_API_URL).then((r) => r.json()); |
| 36 | const nightly = Array.isArray(list) |
| 37 | ? list.find((release) => release.tag_name?.includes("-nightly.")) |
| 38 | : undefined; |
| 39 | if (!nightly) throw new Error("No nightly release in the latest page"); |
| 40 | return nightly; |
| 41 | } |
| 42 | |
| 43 | export async function fetchLatestRelease(channel: ReleaseChannel = "stable"): Promise<Release> { |
| 44 | const key = cacheKey(channel); |
| 45 | const cached = sessionStorage.getItem(key); |
| 46 | if (cached) return JSON.parse(cached); |
| 47 | |
| 48 | const data = channel === "nightly" ? await fetchNightly() : await fetchStable(); |
| 49 | |
| 50 | if (data?.assets) { |
| 51 | sessionStorage.setItem(key, JSON.stringify(data)); |
| 52 | } |
| 53 | |
| 54 | return data; |
| 55 | } |