fix: fallback to legacy keys for variant lookup
This commit is contained in:
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { getDb } from "@tline/db";
|
import { getDb } from "@tline/db";
|
||||||
import { presignGetObjectUrl } from "@tline/minio";
|
import { presignGetObjectUrl } from "@tline/minio";
|
||||||
import { pickVariantKey } from "./variant";
|
import { pickLegacyKeyForRequest, pickVariantKey } from "./variant";
|
||||||
|
|
||||||
export const runtime = "nodejs";
|
export const runtime = "nodejs";
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ const paramsSchema = z.object({
|
|||||||
const legacyVariantSchema = z.enum(["original", "thumb_small", "thumb_med", "poster"]);
|
const legacyVariantSchema = z.enum(["original", "thumb_small", "thumb_med", "poster"]);
|
||||||
const kindSchema = z.enum(["original", "thumb", "poster", "video_mp4"]);
|
const kindSchema = z.enum(["original", "thumb", "poster", "video_mp4"]);
|
||||||
const sizeSchema = z.coerce.number().int().positive();
|
const sizeSchema = z.coerce.number().int().positive();
|
||||||
|
const videoMp4DefaultSize = 720;
|
||||||
const legacyVariantMap = {
|
const legacyVariantMap = {
|
||||||
original: { kind: "original" as const },
|
original: { kind: "original" as const },
|
||||||
thumb_small: { kind: "thumb" as const, size: 256 },
|
thumb_small: { kind: "thumb" as const, size: 256 },
|
||||||
@@ -53,14 +54,18 @@ export async function GET(
|
|||||||
}
|
}
|
||||||
requestedKind = kindParsed.data;
|
requestedKind = kindParsed.data;
|
||||||
if (requestedKind !== "original") {
|
if (requestedKind !== "original") {
|
||||||
const sizeParsed = sizeSchema.safeParse(sizeParam);
|
if (requestedKind === "video_mp4" && !sizeParam) {
|
||||||
if (!sizeParsed.success) {
|
requestedSize = videoMp4DefaultSize;
|
||||||
return Response.json(
|
} else {
|
||||||
{ error: "invalid_query", issues: sizeParsed.error.issues },
|
const sizeParsed = sizeSchema.safeParse(sizeParam);
|
||||||
{ status: 400 },
|
if (!sizeParsed.success) {
|
||||||
);
|
return Response.json(
|
||||||
|
{ error: "invalid_query", issues: sizeParsed.error.issues },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
requestedSize = sizeParsed.data;
|
||||||
}
|
}
|
||||||
requestedSize = sizeParsed.data;
|
|
||||||
}
|
}
|
||||||
} else if (legacyVariantParam) {
|
} else if (legacyVariantParam) {
|
||||||
const legacyParsed = legacyVariantSchema.safeParse(legacyVariantParam);
|
const legacyParsed = legacyVariantSchema.safeParse(legacyVariantParam);
|
||||||
@@ -113,14 +118,17 @@ export async function GET(
|
|||||||
return Response.json({ error: "not_found" }, { status: 404 });
|
return Response.json({ error: "not_found" }, { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const legacyKey =
|
const legacyKey = legacyVariant
|
||||||
legacyVariant === "thumb_small"
|
? pickLegacyKeyForRequest(
|
||||||
? asset.thumb_small_key
|
{ asset },
|
||||||
: legacyVariant === "thumb_med"
|
{ kind: requestedKind, size: requestedSize ?? 0 },
|
||||||
? asset.thumb_med_key
|
)
|
||||||
: legacyVariant === "poster"
|
: requestedSize !== null
|
||||||
? asset.poster_key
|
? pickLegacyKeyForRequest(
|
||||||
: null;
|
{ asset },
|
||||||
|
{ kind: requestedKind, size: requestedSize },
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
const key =
|
const key =
|
||||||
requestedKind === "original"
|
requestedKind === "original"
|
||||||
|
|||||||
@@ -7,3 +7,25 @@ export function pickVariantKey(
|
|||||||
);
|
);
|
||||||
return v?.key ?? null;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,33 @@
|
|||||||
import { test, expect } from "bun:test";
|
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(
|
const { pickVariantKey } = await import(
|
||||||
"../../app/api/assets/[id]/url/variant",
|
"../../app/api/assets/[id]/url/variant",
|
||||||
);
|
);
|
||||||
const key = pickVariantKey({ variants: [] }, { kind: "thumb", size: 256 });
|
const key = pickVariantKey({ variants: [] }, { kind: "thumb", size: 256 });
|
||||||
expect(key).toBeNull();
|
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();
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user