Browse Source

refactor: extract buildMediaResponse and capabilitiesForMediaType helpers

Deduplicate the media response block (3d/video/audio/image) that was
copy-pasted across all 4 provider branches, and the mediaType-to-
capabilities ternary chain repeated 4 times.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 5 months ago
parent
commit
0e60901e39
  1. 225
      src/app/api/generate/route.ts

225
src/app/api/generate/route.ts

@ -37,6 +37,51 @@ interface MultiProviderGenerateRequest extends GenerateRequest {
}
function buildMediaResponse(output: { type: string; data: string; url?: string }): NextResponse {
if (output.type === "3d") {
return NextResponse.json<GenerateResponse>({
success: true,
model3dUrl: output.url,
contentType: "3d",
});
}
if (output.type === "video") {
const isLarge = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
video: isLarge ? undefined : output.data,
videoUrl: isLarge ? output.url : undefined,
contentType: "video",
});
}
if (output.type === "audio") {
const isLarge = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
audio: isLarge ? undefined : output.data,
audioUrl: isLarge ? output.url : undefined,
contentType: "audio",
});
}
return NextResponse.json<GenerateResponse>({
success: true,
image: output.data,
contentType: "image",
});
}
function capabilitiesForMediaType(mediaType?: string): string[] {
const map: Record<string, string[]> = {
audio: ["text-to-audio"],
video: ["text-to-video"],
"3d": ["text-to-3d"],
};
return map[mediaType ?? ""] ?? ["text-to-image"];
}
export async function POST(request: NextRequest) {
const requestId = Math.random().toString(36).substring(7);
console.log(`\n[API:${requestId}] ========== NEW GENERATE REQUEST ==========`);
@ -125,7 +170,7 @@ export async function POST(request: NextRequest) {
id: selectedModel!.modelId,
name: selectedModel!.displayName,
provider: "replicate",
capabilities: mediaType === "audio" ? ["text-to-audio"] : mediaType === "video" ? ["text-to-video"] : mediaType === "3d" ? ["text-to-3d"] : ["text-to-image"],
capabilities: capabilitiesForMediaType(mediaType),
description: null,
},
prompt: prompt || "",
@ -146,53 +191,16 @@ export async function POST(request: NextRequest) {
);
}
// Return first output (image or video)
// Return first output
const output = result.outputs?.[0];
if (!output?.data && !output?.url) {
return NextResponse.json<GenerateResponse>(
{
success: false,
error: "No output in generation result",
},
{ success: false, error: "No output in generation result" },
{ status: 500 }
);
}
// Return appropriate fields based on output type
if (output.type === "3d") {
return NextResponse.json<GenerateResponse>({
success: true,
model3dUrl: output.url,
contentType: "3d",
});
}
if (output.type === "video") {
// Large videos have data="" with url set; normal videos have base64 data
const isLargeVideo = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
video: isLargeVideo ? undefined : output.data,
videoUrl: isLargeVideo ? output.url : undefined,
contentType: "video",
});
}
if (output.type === "audio") {
const isLargeAudio = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
audio: isLargeAudio ? undefined : output.data,
audioUrl: isLargeAudio ? output.url : undefined,
contentType: "audio",
});
}
return NextResponse.json<GenerateResponse>({
success: true,
image: output.data,
contentType: "image",
});
return buildMediaResponse(output);
}
if (provider === "fal") {
@ -230,7 +238,7 @@ export async function POST(request: NextRequest) {
id: selectedModel!.modelId,
name: selectedModel!.displayName,
provider: "fal",
capabilities: mediaType === "audio" ? ["text-to-audio"] : mediaType === "video" ? ["text-to-video"] : mediaType === "3d" ? ["text-to-3d"] : ["text-to-image"],
capabilities: capabilitiesForMediaType(mediaType),
description: null,
},
prompt: prompt || "",
@ -251,53 +259,16 @@ export async function POST(request: NextRequest) {
);
}
// Return first output (image or video)
// Return first output
const output = result.outputs?.[0];
if (!output?.data && !output?.url) {
return NextResponse.json<GenerateResponse>(
{
success: false,
error: "No output in generation result",
},
{ success: false, error: "No output in generation result" },
{ status: 500 }
);
}
// Return appropriate fields based on output type
if (output.type === "3d") {
return NextResponse.json<GenerateResponse>({
success: true,
model3dUrl: output.url,
contentType: "3d",
});
}
if (output.type === "video") {
// Large videos have data="" with url set; normal videos have base64 data
const isLargeVideo = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
video: isLargeVideo ? undefined : output.data,
videoUrl: isLargeVideo ? output.url : undefined,
contentType: "video",
});
}
if (output.type === "audio") {
const isLargeAudio = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
audio: isLargeAudio ? undefined : output.data,
audioUrl: isLargeAudio ? output.url : undefined,
contentType: "audio",
});
}
return NextResponse.json<GenerateResponse>({
success: true,
image: output.data,
contentType: "image",
});
return buildMediaResponse(output);
}
if (provider === "kie") {
@ -339,7 +310,7 @@ export async function POST(request: NextRequest) {
id: selectedModel!.modelId,
name: selectedModel!.displayName,
provider: "kie",
capabilities: mediaType === "audio" ? ["text-to-audio"] : mediaType === "video" ? ["text-to-video"] : mediaType === "3d" ? ["text-to-3d"] : ["text-to-image"],
capabilities: capabilitiesForMediaType(mediaType),
description: null,
},
prompt: prompt || "",
@ -360,53 +331,16 @@ export async function POST(request: NextRequest) {
);
}
// Return first output (image or video)
// Return first output
const output = result.outputs?.[0];
if (!output?.data && !output?.url) {
return NextResponse.json<GenerateResponse>(
{
success: false,
error: "No output in generation result",
},
{ success: false, error: "No output in generation result" },
{ status: 500 }
);
}
// Return appropriate fields based on output type
if (output.type === "3d") {
return NextResponse.json<GenerateResponse>({
success: true,
model3dUrl: output.url,
contentType: "3d",
});
}
if (output.type === "video") {
// Large videos have data="" with url set; normal videos have base64 data
const isLargeVideo = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
video: isLargeVideo ? undefined : output.data,
videoUrl: isLargeVideo ? output.url : undefined,
contentType: "video",
});
}
if (output.type === "audio") {
const isLargeAudio = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
audio: isLargeAudio ? undefined : output.data,
audioUrl: isLargeAudio ? output.url : undefined,
contentType: "audio",
});
}
return NextResponse.json<GenerateResponse>({
success: true,
image: output.data,
contentType: "image",
});
return buildMediaResponse(output);
}
if (provider === "wavespeed") {
@ -448,7 +382,7 @@ export async function POST(request: NextRequest) {
id: selectedModel!.modelId,
name: selectedModel!.displayName,
provider: "wavespeed",
capabilities: mediaType === "audio" ? ["text-to-audio"] : mediaType === "video" ? ["text-to-video"] : mediaType === "3d" ? ["text-to-3d"] : ["text-to-image"],
capabilities: capabilitiesForMediaType(mediaType),
description: null,
},
prompt: prompt || "",
@ -469,53 +403,16 @@ export async function POST(request: NextRequest) {
);
}
// Return first output (image or video)
// Return first output
const output = result.outputs?.[0];
if (!output?.data && !output?.url) {
return NextResponse.json<GenerateResponse>(
{
success: false,
error: "No output in generation result",
},
{ success: false, error: "No output in generation result" },
{ status: 500 }
);
}
// Return appropriate fields based on output type
if (output.type === "3d") {
return NextResponse.json<GenerateResponse>({
success: true,
model3dUrl: output.url,
contentType: "3d",
});
}
if (output.type === "video") {
// Large videos have data="" with url set; normal videos have base64 data
const isLargeVideo = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
video: isLargeVideo ? undefined : output.data,
videoUrl: isLargeVideo ? output.url : undefined,
contentType: "video",
});
}
if (output.type === "audio") {
const isLargeAudio = !output.data && output.url;
return NextResponse.json<GenerateResponse>({
success: true,
audio: isLargeAudio ? undefined : output.data,
audioUrl: isLargeAudio ? output.url : undefined,
contentType: "audio",
});
}
return NextResponse.json<GenerateResponse>({
success: true,
image: output.data,
contentType: "image",
});
return buildMediaResponse(output);
}
// Default: Use Gemini

Loading…
Cancel
Save