From e48c7051d944e5ce44d9555799b640fdd93ae9a5 Mon Sep 17 00:00:00 2001 From: Justin Duke Date: Thu, 3 Oct 2024 15:15:19 -0400 Subject: [PATCH] Add basic /domains API --- app/api/domains/route.ts | 30 ++++++++++++++++++++++ app/technology/[identifier]/page.tsx | 37 +++++++--------------------- lib/db/domains-by-technology.ts | 22 +++++++++++++++++ 3 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 app/api/domains/route.ts create mode 100644 lib/db/domains-by-technology.ts diff --git a/app/api/domains/route.ts b/app/api/domains/route.ts new file mode 100644 index 0000000..7347f44 --- /dev/null +++ b/app/api/domains/route.ts @@ -0,0 +1,30 @@ +import fetchDomainsByTechnology from "@/lib/db/domains-by-technology"; +import { NextRequest } from "next/server"; + +export async function GET( + request: NextRequest, + context: { + }, +) { + const technology = request.nextUrl.searchParams.get("technology"); + if (!technology) { + return Response.json({ + error: "Missing required parameter: technology", + }, { + status: 400, + }); + } + + const data = await fetchDomainsByTechnology(technology, 100); + return Response.json({ + // We really need to decide on some sort of way to enforce a contract here. + // Maybe zod-openapi? + data: data.data.map((item) => { + return { + domain: item.domain, + creation_date: item.creation_date, + } + }).sort((a, b) => b.creation_date.getTime() - a.creation_date.getTime()), + count: data.count, + }); +} diff --git a/app/technology/[identifier]/page.tsx b/app/technology/[identifier]/page.tsx index ffa7365..0138ba6 100644 --- a/app/technology/[identifier]/page.tsx +++ b/app/technology/[identifier]/page.tsx @@ -1,13 +1,14 @@ import Grid from "@/components/Grid"; import Header from "@/components/Header"; import { db } from "@/lib/db/connection"; +import fetchDomainsByTechnology from "@/lib/db/domains-by-technology"; import { GENRE_REGISTRY, REGISTRY } from "@/lib/services"; import * as Dialog from "@radix-ui/react-dialog"; -const PAGE_SIZE = 101; - const SHOVEL_PRO_URL = process.env.SHOVEL_PRO_URL; +const PAGE_SIZE = 100; + import { Metadata, ResolvingMetadata } from "next"; type Props = { @@ -35,27 +36,7 @@ export default async function TechnologyPage({ params: { identifier: string }; }) { const service = REGISTRY[params.identifier]; - const data = process.env.DISABLE_DATABASE - ? { data: [], moreCount: 0 } - : await db - .selectFrom("detected_technologies") - .where("technology", "=", params.identifier) - .selectAll() - .distinctOn("domain") - .execute() - .then((results) => { - if (results.length > PAGE_SIZE) { - const moreCount = results.length - PAGE_SIZE; - return { - data: results.slice(0, PAGE_SIZE), - moreCount, - }; - } - return { - data: results, - moreCount: 0, - }; - }); + const data = await fetchDomainsByTechnology(params.identifier, PAGE_SIZE); const technologyCounts = process.env.DISABLE_DATABASE ? [] @@ -118,10 +99,10 @@ export default async function TechnologyPage({ {trancoCount > 0 ? ( (trancoCount * 100) / - (data.data.length + data.moreCount) + (data.count) ).toFixed(2) : "0.00"} - %) / {data.data.length + data.moreCount} total domains + %) / {data.count} total domains @@ -139,14 +120,14 @@ export default async function TechnologyPage({
{item.domain}
))} - {data.moreCount > 0 && ( + {data.count > PAGE_SIZE && (
{/* Note: This component should be moved to a client-side component */} @@ -191,7 +172,7 @@ export default async function TechnologyPage({ {item.count} ( {( (Number(item.count) * 100) / - (data.data.length + data.moreCount) + (data.count) ).toFixed(2)} %)
diff --git a/lib/db/domains-by-technology.ts b/lib/db/domains-by-technology.ts new file mode 100644 index 0000000..9e29bf2 --- /dev/null +++ b/lib/db/domains-by-technology.ts @@ -0,0 +1,22 @@ +import { db } from "@/lib/db/connection"; + +const fetchDomainsByTechnology = async (technology: string, limit: number) => { + const data = process.env.DISABLE_DATABASE + ? { data: [], count: 0 } + : await db + .selectFrom("detected_technologies") + .where("technology", "=", technology) + .selectAll() + .distinctOn("domain") + .execute() + .then((results) => { + return { + data: results.slice(0, limit), + count: results.length, + }; + }); + + return data; +}; + +export default fetchDomainsByTechnology;