Skip to content

Commit

Permalink
refactor: move all db calls to server action files and abstract funct…
Browse files Browse the repository at this point in the history
…ions into separate files
  • Loading branch information
youngbloodcyb committed Jul 18, 2024
1 parent 99959ca commit 9f6c464
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 122 deletions.
194 changes: 72 additions & 122 deletions main/app/api/endpoints/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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(
Expand All @@ -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 });
}
}
Expand All @@ -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 });
}
}
8 changes: 8 additions & 0 deletions main/lib/data/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions main/lib/data/leads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
18 changes: 18 additions & 0 deletions main/lib/data/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
9 changes: 9 additions & 0 deletions main/lib/helpers/construct-body.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const constructBodyFromURLParameters = (
searchParams: URLSearchParams
): Record<string, string> => {
const data: Record<string, string> = {};
for (const [key, value] of searchParams) {
data[key] = value;
}
return data;
};

0 comments on commit 9f6c464

Please sign in to comment.