diff --git a/main/app/api/endpoints/[id]/route.ts b/main/app/api/endpoints/[id]/route.ts index 78535b0..bc20d5a 100644 --- a/main/app/api/endpoints/[id]/route.ts +++ b/main/app/api/endpoints/[id]/route.ts @@ -1,14 +1,15 @@ import { NextResponse } from "next/server"; -import { db } from "@/lib/db/db"; -import { endpoints, logs, leads } from "@/lib/db/schema"; -import { eq } from "drizzle-orm"; import { convertToCorrectTypes, generateDynamicSchema, validateAndParseData, } from "@/lib/validation"; import { headers } from "next/headers"; -import { revalidatePath } from "next/cache"; +import { getEndpointByIncrementId } from "@/lib/data/endpoints"; +import { createLead } from "@/lib/data/leads"; +import { createLog } from "@/lib/data/logs"; +import { getErrorMessage } from "@/lib/helpers/error-message"; +import { constructBodyFromURLParameters } from "@/lib/helpers/construct-body"; export async function POST( request: Request, @@ -37,18 +38,13 @@ export async function POST( const data = await request.json(); - const endpointResult = await db - .select() - .from(endpoints) - .where(eq(endpoints.incrementId, parsedId)); - const endpoint = endpointResult[0]; + const endpoint = await getEndpointByIncrementId(parsedId); - if (!endpoint) { + if (!endpoint) return NextResponse.json( { message: "Endpoint not found." }, { status: 404 } ); - } if (endpoint.token !== token) { return NextResponse.json( @@ -62,51 +58,29 @@ export async function POST( const parsedData = validateAndParseData(dynamicSchema, data); if (!parsedData.success) { - await db.insert(logs).values({ - type: "error", - postType: "http", - message: JSON.stringify(parsedData.error.format()), - createdAt: new Date(), - endpointId: endpoint.id, - }); - revalidatePath("/logs"); + createLog( + "error", + "http", + JSON.stringify(parsedData.error.format()), + endpoint.id + ); + return NextResponse.json( { errors: parsedData.error.format() }, { status: 400 } ); } - const insertedLead = await db - .insert(leads) - .values({ - data: parsedData.data, - createdAt: new Date(), - updatedAt: new Date(), - endpointId: endpoint.id, - }) - .returning({ insertedId: leads.id }); - - await db.insert(logs).values({ - type: "success", - postType: "http", - message: { success: insertedLead[0].insertedId }, - createdAt: new Date(), - endpointId: endpoint.id, - }); - revalidatePath("/logs"); - - return NextResponse.json({ id: insertedLead[0].insertedId }); - } catch (error) { - // create a log of the error - await db.insert(logs).values({ - type: "error", - postType: "http", - message: JSON.stringify(error), - createdAt: new Date(), - endpointId: params.id, - }); - revalidatePath("/logs"); + const leadId = await createLead(endpoint.id, parsedData.data); + + await createLog("success", "http", leadId, endpoint.id); + + return NextResponse.json({ success: true, id: leadId }); + } catch (error: unknown) { + await createLog("error", "http", getErrorMessage(error), params.id); + console.error(error); + return NextResponse.json({ error: "An error occurred." }, { status: 500 }); } } @@ -115,83 +89,59 @@ export async function GET( request: Request, { params }: { params: { id: string } } ) { - const headersList = headers(); - const referer = headersList.get("referer"); - // get URL search parameters - const { searchParams } = new URL(request.url); - - // parse the ID from the URL and return a 400 if it's not a number - const parsedId = parseInt(params.id); - if (isNaN(parsedId)) { - return NextResponse.json( - { message: "Invalid ID provided." }, - { status: 400 } - ); - } + try { + const headersList = headers(); + const referer = headersList.get("referer"); + const { searchParams } = new URL(request.url); - // get the endpoint from the database - const endpointResult = await db - .select() - .from(endpoints) - .where(eq(endpoints.incrementId, parsedId)); - const endpoint = endpointResult[0]; - - // if the endpoint doesn't exist, return a 404 - if (!endpoint) { - return NextResponse.json( - { message: "Endpoint not found." }, - { status: 404 } - ); - } + const parsedId = parseInt(params.id); + if (isNaN(parsedId)) { + return NextResponse.json( + { message: "Invalid ID provided." }, + { status: 400 } + ); + } - // get the data from the URL search parameters - const rawData: any = {}; - for (const [key, value] of searchParams) { - rawData[key] = value; - } + const endpoint = await getEndpointByIncrementId(parsedId); + + if (!endpoint) { + return NextResponse.json( + { message: "Endpoint not found." }, + { status: 404 } + ); + } + + const rawData = constructBodyFromURLParameters(searchParams); + const schema = endpoint?.schema as GeneralSchema[]; + const data = convertToCorrectTypes(rawData, schema); + const dynamicSchema = generateDynamicSchema(schema); + const parsedData = validateAndParseData(dynamicSchema, data); + + if (!parsedData.success) { + createLog( + "error", + "http", + JSON.stringify(parsedData.error.format()), + endpoint.id + ); + + return NextResponse.redirect( + new URL(endpoint?.failUrl || referer || "/fail") + ); + } + + const leadId = await createLead(endpoint.id, parsedData.data); + + await createLog("success", "http", leadId, endpoint.id); - // get the schema from the endpoint - const schema = endpoint?.schema as GeneralSchema[]; - // convert the data to the correct types - const data = convertToCorrectTypes(rawData, schema); - const dynamicSchema = generateDynamicSchema(schema); - const parsedData = validateAndParseData(dynamicSchema, data); - - if (!parsedData.success) { - await db.insert(logs).values({ - type: "error", - postType: "form", - message: JSON.stringify(parsedData.error.format()), - createdAt: new Date(), - endpointId: endpoint.id, - }); - revalidatePath("/logs"); return NextResponse.redirect( - new URL(endpoint?.failUrl || referer || "/fail") + new URL(endpoint?.successUrl || referer || "/success") ); - } + } catch (error: unknown) { + await createLog("error", "http", getErrorMessage(error), params.id); + + console.error(error); - // insert the lead into the database - const insertedLead = await db - .insert(leads) - .values({ - data: parsedData.data, - createdAt: new Date(), - updatedAt: new Date(), - endpointId: endpoint.id, - }) - .returning({ insertedId: leads.id }); - - await db.insert(logs).values({ - type: "success", - postType: "form", - message: { success: insertedLead[0].insertedId }, - createdAt: new Date(), - endpointId: endpoint.id, - }); - revalidatePath("/logs"); - - return NextResponse.redirect( - new URL(endpoint?.successUrl || referer || "/success") - ); + return NextResponse.json({ error: "An error occurred." }, { status: 500 }); + } } diff --git a/main/lib/data/endpoints.ts b/main/lib/data/endpoints.ts index 71079b4..1abe89e 100644 --- a/main/lib/data/endpoints.ts +++ b/main/lib/data/endpoints.ts @@ -16,6 +16,14 @@ export async function getEndpoints(userId: string) { return data; } +export async function getEndpointByIncrementId(incrementId: number) { + const [data] = await db + .select() + .from(endpoints) + .where(eq(endpoints.incrementId, incrementId)); + return data; +} + export async function getEndpointById(id: string) { const [data] = await db.select().from(endpoints).where(eq(endpoints.id, id)); return data; diff --git a/main/lib/data/leads.ts b/main/lib/data/leads.ts index 753797f..6cd70c1 100644 --- a/main/lib/data/leads.ts +++ b/main/lib/data/leads.ts @@ -6,6 +6,25 @@ import { revalidatePath } from "next/cache"; import { db } from "../db/db"; import { getErrorMessage } from "@/lib/helpers/error-message"; +export async function createLead( + endpointId: string, + data: { + [x: string]: any; + } +) { + const [{ leadId }] = await db + .insert(leads) + .values({ + data, + createdAt: new Date(), + updatedAt: new Date(), + endpointId: endpointId, + }) + .returning({ leadId: leads.id }); + + return leadId; +} + export async function getLeads(userId: string) { const leadsData = await db .select() diff --git a/main/lib/data/logs.ts b/main/lib/data/logs.ts index ed16d71..fb49b41 100644 --- a/main/lib/data/logs.ts +++ b/main/lib/data/logs.ts @@ -6,6 +6,24 @@ import { revalidatePath } from "next/cache"; import { db } from "../db/db"; import { getErrorMessage } from "@/lib/helpers/error-message"; +export async function createLog( + type: "success" | "error", + postType: "http" | "form", + message: string, + endpointId: string +) { + await db.insert(logs).values({ + type, + postType, + message: + type === "success" ? { success: true, id: message } : { error: message }, + createdAt: new Date(), + endpointId, + }); + + revalidatePath("/logs"); +} + export async function getLogs(userId: string) { const logsData = await db .select() diff --git a/main/lib/helpers/construct-body.ts b/main/lib/helpers/construct-body.ts new file mode 100644 index 0000000..6672492 --- /dev/null +++ b/main/lib/helpers/construct-body.ts @@ -0,0 +1,9 @@ +export const constructBodyFromURLParameters = ( + searchParams: URLSearchParams +): Record => { + const data: Record = {}; + for (const [key, value] of searchParams) { + data[key] = value; + } + return data; +};