mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 23:18:44 -07:00
eb73f3c484
Review follow-ups: - The downloads routes now answer only on the apex (the site's host) and 404 on every other accepted host, so the game's open API/CDN subdomains can't serve the builds. - Install on Quest passes its own file to the Quest page instead of always picking the newest release. - Waiting for the bucket's headers is limited to 30 s; the body still streams without a limit. - Dispose the upstream request message; use LINQ in FindFile.
60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
// The client builds CI publishes (ci/downloads/publish.py), served through
|
|
// the server's DownloadsController. The manifest keeps the snake_case keys
|
|
// publish.py writes.
|
|
import { ApiError, get } from './api';
|
|
|
|
export interface DownloadFile {
|
|
id: string; // pc-full | pc-patch | quest | quest-installer
|
|
platform: 'pc' | 'quest' | string;
|
|
name: string;
|
|
path: string;
|
|
size: number;
|
|
sha256: string;
|
|
build?: string;
|
|
commit?: string;
|
|
built_at?: string;
|
|
}
|
|
|
|
export interface DownloadRelease {
|
|
id: string;
|
|
title: string;
|
|
game_version?: string;
|
|
pc_exe?: string;
|
|
files: DownloadFile[];
|
|
}
|
|
|
|
export interface DownloadsManifest {
|
|
releases: DownloadRelease[];
|
|
updated?: string;
|
|
}
|
|
|
|
let cached: Promise<DownloadsManifest | null> | null = null;
|
|
|
|
/** The manifest, or null when this server doesn't offer downloads. Fetched
|
|
* once per page load; pass `fresh` to re-read it. */
|
|
export function getDownloads(fresh = false): Promise<DownloadsManifest | null> {
|
|
if (!cached || fresh) {
|
|
cached = get<DownloadsManifest>('/downloads').catch((e) => {
|
|
if (e instanceof ApiError && e.status === 404) return null;
|
|
cached = null;
|
|
throw e;
|
|
});
|
|
}
|
|
return cached;
|
|
}
|
|
|
|
export const fileUrl = (f: DownloadFile) =>
|
|
`/api/site/v1/downloads/files/${f.path.split('/').map(encodeURIComponent).join('/')}`;
|
|
|
|
export interface QuestBuild { release: DownloadRelease; file: DownloadFile }
|
|
|
|
/** A published Quest package: the one at `path` when given, otherwise the
|
|
* newest release's. Null when there's no match. */
|
|
export function questBuild(m: DownloadsManifest | null, path?: string | null): QuestBuild | null {
|
|
for (const release of m?.releases ?? []) {
|
|
const file = release.files.find((f) => f.id === 'quest' && (!path || f.path === path));
|
|
if (file) return { release, file };
|
|
}
|
|
return null;
|
|
}
|