Files
elysium/apps/api/src/routes/about.ts
T
hikari e17278d5f2
CI / Lint, Build & Test (pull_request) Successful in 1m15s
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m15s
chore: update gitea releases url to new org path
2026-03-08 15:43:31 -07:00

58 lines
1.7 KiB
TypeScript

/**
* @file About route providing API version and release information.
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable stylistic/max-len -- URL cannot be shortened */
/* eslint-disable require-atomic-updates -- Simple cache; race condition is acceptable */
import { Hono } from "hono";
import type { AboutResponse, GiteaRelease } from "@elysium/types";
// eslint-disable-next-line capitalized-comments -- v8 ignore
/* v8 ignore next -- @preserve */
const apiVersion = process.env.npm_package_version ?? "unknown";
const giteaReleasesUrl = "https://git.nhcarrigan.com/api/v1/repos/nhcarrigan/elysium/releases";
const cacheTtlMs = 5 * 60 * 1000;
interface ReleasesCache {
data: Array<GiteaRelease>;
timestamp: number;
}
let releasesCache: ReleasesCache = { data: [], timestamp: 0 };
const fetchReleases = async(): Promise<Array<GiteaRelease>> => {
const now = Date.now();
if (releasesCache.data.length > 0 && now - releasesCache.timestamp < cacheTtlMs) {
return releasesCache.data;
}
try {
const response = await fetch(giteaReleasesUrl);
if (!response.ok) {
return releasesCache.data;
}
const rawData: unknown = await response.json();
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- External API response */
const data = rawData as Array<GiteaRelease>;
releasesCache = { data: data, timestamp: now };
return releasesCache.data;
} catch {
return releasesCache.data;
}
};
const aboutRouter = new Hono();
aboutRouter.get("/", async(context) => {
const releases = await fetchReleases();
const body: AboutResponse = {
apiVersion,
releases,
};
return context.json(body);
});
export { aboutRouter };