77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
// Helpers for resolving uploaded-asset URLs out of loosely-typed API records.
|
|
// Response field names vary across endpoints, so we probe a list of common keys
|
|
// and turn relative storage paths into absolute URLs.
|
|
|
|
import { ASSET_BASE_URL } from "./config";
|
|
|
|
// Turn a possibly-relative path into an absolute URL. The API serves uploads
|
|
// from `/storage/...`, while DB fields like `file_path` hold paths relative to
|
|
// that (e.g. "music/x.mp3"), so we add the `storage/` prefix when missing.
|
|
export function assetUrl(path?: string | null): string | null {
|
|
if (!path) return null;
|
|
if (/^(https?:|data:|blob:)/i.test(path)) return path;
|
|
let p = String(path).replace(/^\/+/, "");
|
|
if (!p.startsWith("storage/")) p = `storage/${p}`;
|
|
return `${ASSET_BASE_URL}/${p}`;
|
|
}
|
|
|
|
// A record may store a media reference directly (string) or nested in an object
|
|
// (e.g. { sound: { url } }). Read the first key that yields a usable value.
|
|
function readField(row: Record<string, unknown>, key: string): string | null {
|
|
const v = row[key];
|
|
if (typeof v === "string" && v) return v;
|
|
if (v && typeof v === "object") {
|
|
const obj = v as Record<string, unknown>;
|
|
for (const k of ["url", "path", "src", "file"]) {
|
|
if (typeof obj[k] === "string" && obj[k]) return obj[k] as string;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Find the first present URL among candidate keys, resolved to absolute.
|
|
export function pickUrl(
|
|
row: unknown,
|
|
keys: string[],
|
|
): string | null {
|
|
if (!row || typeof row !== "object") return null;
|
|
const record = row as Record<string, unknown>;
|
|
for (const key of keys) {
|
|
const found = readField(record, key);
|
|
if (found) return assetUrl(found);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Common key sets per media kind. Ordered most-specific / full-URL first.
|
|
// (`/media` returns the playable file in `external_url`; `/music` uses `url`.)
|
|
export const SOUND_KEYS = [
|
|
"url",
|
|
"external_url",
|
|
"sound_url",
|
|
"sound",
|
|
"audio_url",
|
|
"audio",
|
|
"file_url",
|
|
"file",
|
|
"file_path",
|
|
];
|
|
export const VIDEO_KEYS = [
|
|
"external_url",
|
|
"video_url",
|
|
"video",
|
|
"url",
|
|
"file_url",
|
|
"file",
|
|
"file_path",
|
|
];
|
|
export const IMAGE_KEYS = [
|
|
"image_url",
|
|
"image",
|
|
"thumbnail",
|
|
"thumbnail_url",
|
|
"cover",
|
|
"url",
|
|
"path",
|
|
];
|