fix: fallback to legacy keys for variant lookup

This commit is contained in:
William Valentin
2026-02-01 12:13:39 -08:00
parent 26e2d74d2b
commit 517e21d0b7
3 changed files with 71 additions and 17 deletions

View File

@@ -2,7 +2,7 @@ import { z } from "zod";
import { getDb } from "@tline/db";
import { presignGetObjectUrl } from "@tline/minio";
import { pickVariantKey } from "./variant";
import { pickLegacyKeyForRequest, pickVariantKey } from "./variant";
export const runtime = "nodejs";
@@ -13,6 +13,7 @@ const paramsSchema = z.object({
const legacyVariantSchema = z.enum(["original", "thumb_small", "thumb_med", "poster"]);
const kindSchema = z.enum(["original", "thumb", "poster", "video_mp4"]);
const sizeSchema = z.coerce.number().int().positive();
const videoMp4DefaultSize = 720;
const legacyVariantMap = {
original: { kind: "original" as const },
thumb_small: { kind: "thumb" as const, size: 256 },
@@ -53,14 +54,18 @@ export async function GET(
}
requestedKind = kindParsed.data;
if (requestedKind !== "original") {
const sizeParsed = sizeSchema.safeParse(sizeParam);
if (!sizeParsed.success) {
return Response.json(
{ error: "invalid_query", issues: sizeParsed.error.issues },
{ status: 400 },
);
if (requestedKind === "video_mp4" && !sizeParam) {
requestedSize = videoMp4DefaultSize;
} else {
const sizeParsed = sizeSchema.safeParse(sizeParam);
if (!sizeParsed.success) {
return Response.json(
{ error: "invalid_query", issues: sizeParsed.error.issues },
{ status: 400 },
);
}
requestedSize = sizeParsed.data;
}
requestedSize = sizeParsed.data;
}
} else if (legacyVariantParam) {
const legacyParsed = legacyVariantSchema.safeParse(legacyVariantParam);
@@ -113,14 +118,17 @@ export async function GET(
return Response.json({ error: "not_found" }, { status: 404 });
}
const legacyKey =
legacyVariant === "thumb_small"
? asset.thumb_small_key
: legacyVariant === "thumb_med"
? asset.thumb_med_key
: legacyVariant === "poster"
? asset.poster_key
: null;
const legacyKey = legacyVariant
? pickLegacyKeyForRequest(
{ asset },
{ kind: requestedKind, size: requestedSize ?? 0 },
)
: requestedSize !== null
? pickLegacyKeyForRequest(
{ asset },
{ kind: requestedKind, size: requestedSize },
)
: null;
const key =
requestedKind === "original"

View File

@@ -7,3 +7,25 @@ export function pickVariantKey(
);
return v?.key ?? null;
}
export function pickLegacyKeyForRequest(
input: {
asset: {
thumb_small_key: string | null;
thumb_med_key: string | null;
poster_key: string | null;
};
},
req: { kind: string; size: number },
) {
if (req.kind === "thumb" && req.size === 256) {
return input.asset.thumb_small_key ?? null;
}
if (req.kind === "thumb" && req.size === 768) {
return input.asset.thumb_med_key ?? null;
}
if (req.kind === "poster" && req.size === 256) {
return input.asset.poster_key ?? null;
}
return null;
}

View File

@@ -1,9 +1,33 @@
import { test, expect } from "bun:test";
test("/api/assets/:id/url returns 404 when requested variant missing", async () => {
test("variant lookup returns null when no matching variant", async () => {
const { pickVariantKey } = await import(
"../../app/api/assets/[id]/url/variant",
);
const key = pickVariantKey({ variants: [] }, { kind: "thumb", size: 256 });
expect(key).toBeNull();
});
test("legacy fallback maps kind+size to asset keys", async () => {
const { pickLegacyKeyForRequest } = await import(
"../../app/api/assets/[id]/url/variant",
);
const asset = {
thumb_small_key: "thumb-small",
thumb_med_key: "thumb-med",
poster_key: "poster",
};
expect(
pickLegacyKeyForRequest({ asset }, { kind: "thumb", size: 256 }),
).toBe("thumb-small");
expect(
pickLegacyKeyForRequest({ asset }, { kind: "thumb", size: 768 }),
).toBe("thumb-med");
expect(
pickLegacyKeyForRequest({ asset }, { kind: "poster", size: 256 }),
).toBe("poster");
expect(
pickLegacyKeyForRequest({ asset }, { kind: "thumb", size: 1024 }),
).toBeNull();
});