Skip to content

Commit

Permalink
simplify analytics endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
steven-tey committed May 24, 2024
1 parent c45d18d commit 6c7ad03
Show file tree
Hide file tree
Showing 34 changed files with 244 additions and 309 deletions.
1 change: 0 additions & 1 deletion apps/web/app/api/analytics/[endpoint]/route.ts

This file was deleted.

1 change: 1 addition & 0 deletions apps/web/app/api/analytics/[eventType]/[endpoint]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "../../route";
20 changes: 0 additions & 20 deletions apps/web/app/api/analytics/admin/clicks/[endpoint]/route.ts

This file was deleted.

13 changes: 13 additions & 0 deletions apps/web/app/api/analytics/admin/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { getAnalytics } from "@/lib/analytics/get-analytics";
import { withAdmin } from "@/lib/auth";
import { analyticsQuerySchema } from "@/lib/zod/schemas/analytics";
import { NextResponse } from "next/server";

// GET /api/analytics/admin – get analytics for admin
export const GET = withAdmin(async ({ searchParams }) => {
const parsedParams = analyticsQuerySchema.parse(searchParams);

const response = await getAnalytics(parsedParams);

return NextResponse.json(response);
});
48 changes: 0 additions & 48 deletions apps/web/app/api/analytics/clicks/[endpoint]/route.ts

This file was deleted.

1 change: 0 additions & 1 deletion apps/web/app/api/analytics/clicks/route.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import { getAnalytics } from "@/lib/analytics/get-analytics";
import { withSession } from "@/lib/auth";
import {
analyticsEndpointSchema,
analyticsQuerySchema,
} from "@/lib/zod/schemas/analytics";
import { analyticsQuerySchema } from "@/lib/zod/schemas/analytics";
import { NextResponse } from "next/server";

// GET /api/analytics/demo/[eventType]/[endpoint]
export const GET = withSession(async ({ params, searchParams }) => {
const { eventType, endpoint } = analyticsEndpointSchema.parse(params);
const parsedParams = analyticsQuerySchema.parse(searchParams);

const response = await getAnalytics(eventType, {
const response = await getAnalytics({
...parsedParams,
endpoint,
isDemo: true,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,19 @@ import {
} from "@/lib/api/errors";
import { getDomainOrLink, getWorkspaceViaEdge } from "@/lib/planetscale";
import { ratelimit } from "@/lib/upstash";
import {
analyticsEndpointSchema,
analyticsQuerySchema,
} from "@/lib/zod/schemas/analytics";
import { analyticsQuerySchema } from "@/lib/zod/schemas/analytics";
import { DUB_DEMO_LINKS, DUB_WORKSPACE_ID, getSearchParams } from "@dub/utils";
import { ipAddress } from "@vercel/edge";
import { NextResponse, type NextRequest } from "next/server";

export const runtime = "edge";

export const GET = async (
req: NextRequest,
{ params }: { params: Record<string, string> },
) => {
export const GET = async (req: NextRequest) => {
try {
const { endpoint } = analyticsEndpointSchema.parse(params);

const searchParams = getSearchParams(req.url);
const parsedParams = analyticsQuerySchema.parse(searchParams);

const { domain, key, interval, start, end } = parsedParams;
const { type, domain, key, interval, start, end } = parsedParams;

if (!domain || !key) {
throw new DubApiError({
Expand All @@ -49,8 +41,8 @@ export const GET = async (
const ip = ipAddress(req);
const { success } = await ratelimit(
15,
endpoint ? "1 m" : "10 s",
).limit(`demo-analytics:${demoLink.id}:${ip}:${endpoint || "clicks"}`);
type === "count" ? "10 s" : "1 m",
).limit(`demo-analytics:${demoLink.id}:${ip}:${type}`);

if (!success) {
throw new DubApiError({
Expand Down Expand Up @@ -95,11 +87,10 @@ export const GET = async (
}
}

const response = await getAnalytics("clicks", {
const response = await getAnalytics({
...parsedParams,
// workspaceId can be undefined (for public links that haven't been claimed/synced to a workspace)
...(link.projectId && { workspaceId: link.projectId }),
endpoint,
linkId: link.id,
});

Expand Down
15 changes: 8 additions & 7 deletions apps/web/app/api/analytics/export/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
VALID_ANALYTICS_ENDPOINTS,
} from "@/lib/analytics/constants";
import { getAnalytics } from "@/lib/analytics/get-analytics";
import { AnalyticsEndpoints } from "@/lib/analytics/types";
import { validDateRangeForPlan } from "@/lib/analytics/utils";
import { withWorkspace } from "@/lib/auth";
import { getDomainViaEdge } from "@/lib/planetscale";
Expand Down Expand Up @@ -54,10 +53,11 @@ export const GET = withWorkspace(
// since this is just a single link
if (linkId) return;

const data = await getAnalytics("clicks", {
workspaceId: workspace.id,
endpoint: "top_links",
const data = await getAnalytics({
...parsedParams,
event: "clicks",
type: "top_links",
workspaceId: workspace.id,
});

const [links, domains] = await Promise.all([
Expand Down Expand Up @@ -128,11 +128,12 @@ export const GET = withWorkspace(
// skip deprecated endpoints
if (DEPRECATED_ANALYTICS_ENDPOINTS.includes(endpoint)) return;

const response = await getAnalytics("clicks", {
const response = await getAnalytics({
...parsedParams,
workspaceId: workspace.id,
...(linkId && { linkId }),
endpoint: endpoint as AnalyticsEndpoints,
...parsedParams,
event: "clicks",
type: endpoint,
});
if (!response || response.length === 0) return;

Expand Down
48 changes: 0 additions & 48 deletions apps/web/app/api/analytics/leads/[endpoint]/route.ts

This file was deleted.

34 changes: 34 additions & 0 deletions apps/web/app/api/analytics/public-stats/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { withWorkspace } from "@/lib/auth";
import { getDomainOrLink } from "@/lib/planetscale";
import { prisma } from "@/lib/prisma";
import z from "@/lib/zod";
import { domainKeySchema } from "@/lib/zod/schemas/links";
import { NextResponse } from "next/server";

const updatePublicStatsSchema = z.object({
publicStats: z.boolean(),
});

// GET /api/analytics – get the publicStats setting for a link
export const GET = withWorkspace(async ({ searchParams }) => {
const { domain, key } = domainKeySchema.parse(searchParams);
const response = await getDomainOrLink({ domain, key });
return NextResponse.json(response);
});

// PUT /api/analytics – update the publicStats setting for a link
export const PUT = withWorkspace(async ({ req, searchParams }) => {
const { domain, key } = domainKeySchema.parse(searchParams);
const { publicStats } = updatePublicStatsSchema.parse(await req.json());
const response =
key === "_root"
? await prisma.domain.update({
where: { slug: domain },
data: { publicStats },
})
: await prisma.link.update({
where: { domain_key: { domain, key } },
data: { publicStats },
});
return NextResponse.json(response);
});
74 changes: 45 additions & 29 deletions apps/web/app/api/analytics/route.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,50 @@
import { getAnalytics } from "@/lib/analytics/get-analytics";
import { validDateRangeForPlan } from "@/lib/analytics/utils";
import { withWorkspace } from "@/lib/auth";
import { getDomainOrLink } from "@/lib/planetscale";
import { prisma } from "@/lib/prisma";
import z from "@/lib/zod";
import { domainKeySchema } from "@/lib/zod/schemas/links";
import { getDomainViaEdge } from "@/lib/planetscale";
import {
analyticsPathParamsSchema,
analyticsQuerySchema,
} from "@/lib/zod/schemas/analytics";
import { NextResponse } from "next/server";

const updatePublicStatsSchema = z.object({
publicStats: z.boolean(),
});
// GET /api/analytics – get analytics
export const GET = withWorkspace(
async ({ params, searchParams, workspace, link }) => {
const { eventType: oldEvent, endpoint: oldType } =
analyticsPathParamsSchema.parse(params);

// GET /api/analytics – get the publicStats setting for a link
export const GET = withWorkspace(async ({ searchParams }) => {
const { domain, key } = domainKeySchema.parse(searchParams);
const response = await getDomainOrLink({ domain, key });
return NextResponse.json(response);
});
const parsedParams = analyticsQuerySchema.parse(searchParams);
let { event, type, domain, key, interval, start, end } = parsedParams;

// PUT /api/analytics – update the publicStats setting for a link
export const PUT = withWorkspace(async ({ req, searchParams }) => {
const { domain, key } = domainKeySchema.parse(searchParams);
const { publicStats } = updatePublicStatsSchema.parse(await req.json());
const response =
key === "_root"
? await prisma.domain.update({
where: { slug: domain },
data: { publicStats },
})
: await prisma.link.update({
where: { domain_key: { domain, key } },
data: { publicStats },
});
return NextResponse.json(response);
});
event = oldEvent || event;
type = oldType || type;

validDateRangeForPlan({
plan: workspace.plan,
interval,
start,
end,
throwError: true,
});

const linkId = link
? link.id
: domain && key === "_root"
? await getDomainViaEdge(domain).then((d) => d?.id)
: null;

const response = await getAnalytics({
...parsedParams,
event,
type,
...(linkId && { linkId }),
workspaceId: workspace.id,
});

return NextResponse.json(response);
},
{
needNotExceededClicks: true,
},
);
Loading

0 comments on commit 6c7ad03

Please sign in to comment.