feat: add core domain types for Photo Gallery SDK including media items, albums, and annotations

This commit is contained in:
2026-07-23 07:39:01 +05:30
parent 7bcd1a2a2d
commit 2613c767a6
107 changed files with 20699 additions and 7 deletions
+48
View File
@@ -0,0 +1,48 @@
import { type NextRequest, NextResponse } from "next/server";
import { RunpodError } from "@/lib/server/runpod/client";
import { rpTilt } from "@/lib/server/runpod/endpoints";
import { guard } from "../_guard";
export const runtime = "nodejs";
export const maxDuration = 60; // cold-start tilt worker can take a while
export const dynamic = "force-dynamic";
/**
* Camera-tilt estimation proxy. Accepts a base64 image and returns
* {rollDegrees, pitchDegrees, fovDegrees} from the RunPod tilt endpoint
* (RUNPOD_TILT_URL) so the editor can auto-straighten.
*
* POST { image } -> { rollDegrees, pitchDegrees, fovDegrees }
* Auth: session-gated. Rate limit: 30/min.
*/
const MAX_BASE64 = 4_000_000; // ~3 MB decoded
export async function POST(req: NextRequest) {
const gate = await guard(req, "tilt");
if (!gate.ok) return gate.response;
let body: { image?: unknown };
try {
body = await req.json();
} catch {
return NextResponse.json({ error: "Invalid JSON body." }, { status: 400 });
}
const image = typeof body.image === "string" ? body.image : "";
if (!image) return NextResponse.json({ error: "Missing image." }, { status: 400 });
if (image.length > MAX_BASE64) {
return NextResponse.json({ error: "Image too large." }, { status: 413 });
}
try {
const tilt = await rpTilt(image);
return NextResponse.json(tilt);
} catch (e) {
const msg =
e instanceof RunpodError ? e.message : e instanceof Error ? e.message : "Tilt estimate failed.";
return NextResponse.json({ error: msg }, { status: 502 });
}
}