copilot_work_3 / src /app /api /tools /route.ts
Suchinthana Wijesundara
Init commit with project codes
f64a3bf
Raw History Blame
1.98 kB
import { NextResponse } from "next/server";
import { z } from "zod";
import { categories } from "@/lib/tool-types";
import { submitTool } from "@/lib/tools";
const githubRepoUrl = z
.string()
.url()
.refine((value) => {
try {
const url = new URL(value);
return (
url.protocol === "https:" &&
url.hostname === "github.com" &&
!url.username &&
!url.password &&
!url.search &&
!url.hash &&
/^\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\.git)?\/?$/.test(url.pathname)
);
} catch {
return false;
}
}, "Enter a public GitHub repository URL.");
const optionalWebsiteUrl = z
.union([z.literal(""), z.string().url()])
.refine((value) => {
if (!value) return true;
const url = new URL(value);
return url.protocol === "https:" && !url.username && !url.password;
}, "Website must be a public HTTPS URL.");
const submissionSchema = z.object({
name: z.string().trim().min(2).max(80),
summary: z.string().trim().min(20).max(300),
category: z.enum(categories),
repoUrl: githubRepoUrl,
websiteUrl: optionalWebsiteUrl,
submittedBy: z.string().trim().min(2).max(60),
});
export async function POST(request: Request) {
let body: unknown;
try {
body = await request.json();
} catch {
return NextResponse.json({ error: "Request body must be valid JSON." }, { status: 400 });
}
const parsed = submissionSchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json(
{ error: "Please review the submission fields and try again.", fields: parsed.error.flatten().fieldErrors },
{ status: 400 },
);
}
try {
const tool = await submitTool(parsed.data);
return NextResponse.json({ tool }, { status: 201 });
} catch (error) {
console.error("Tool submission failed", error);
return NextResponse.json(
{ error: "The tool could not be saved. Please try again later." },
{ status: 500 },
);
}
}