Skip to content

Commit

Permalink
Merge branch 'main' into utm-templates
Browse files Browse the repository at this point in the history
  • Loading branch information
TWilson023 committed Oct 14, 2024
2 parents dbfe99f + 38ad273 commit 98a78c7
Show file tree
Hide file tree
Showing 115 changed files with 1,843 additions and 812 deletions.
2 changes: 1 addition & 1 deletion apps/web/app/[domain]/placeholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default function PlaceholderContent() {
</motion.p>
<motion.a
variants={STAGGER_CHILD_VARIANTS}
href={createHref("/", domain, {
href={createHref("/home", domain, {
utm_source: "Custom Domain",
utm_medium: "Welcome Page",
utm_campaign: domain,
Expand Down
2 changes: 0 additions & 2 deletions apps/web/app/api/ai/completion/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ export const POST = withWorkspaceEdge(
model,
} = completionSchema.parse(await req.json());

console.log({ prompt });

const result = await streamText({
model: anthropic(model),
messages: [
Expand Down
25 changes: 18 additions & 7 deletions apps/web/app/api/analytics/export/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getLinkOrThrow } from "@/lib/api/links/get-link-or-throw";
import { throwIfClicksUsageExceeded } from "@/lib/api/links/usage-checks";
import { withWorkspace } from "@/lib/auth";
import { analyticsQuerySchema } from "@/lib/zod/schemas/analytics";
import { Link } from "@prisma/client";
import JSZip from "jszip";

// GET /api/analytics/export – get export data for analytics
Expand All @@ -15,14 +16,24 @@ export const GET = withWorkspace(

const parsedParams = analyticsQuerySchema.parse(searchParams);

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

let link: Link | null = null;

if (domain) {
await getDomainOrThrow({ workspace, domain });
}

const link =
domain && key ? await getLinkOrThrow({ workspace, domain, key }) : null;
if (linkId || externalId || (domain && key)) {
link = await getLinkOrThrow({
workspace: workspace,
linkId,
externalId,
domain,
key,
});
}

validDateRangeForPlan({
plan: workspace.plan,
Expand All @@ -36,11 +47,11 @@ export const GET = withWorkspace(

await Promise.all(
VALID_ANALYTICS_ENDPOINTS.map(async (endpoint) => {
// no need to fetch top links data if linkId is defined
// no need to fetch top links data if there's a link specified
// since this is just a single link
if (endpoint === "top_links" && linkId) return;
// we're not fetching top URLs data if linkId is not defined
if (endpoint === "top_urls" && !linkId) return;
if (endpoint === "top_links" && link) return;
// we're not fetching top URLs data if there's no link specified
if (endpoint === "top_urls" && !link) return;
// skip clicks count
if (endpoint === "count") return;

Expand Down
8 changes: 1 addition & 7 deletions apps/web/app/api/auth/account-exists/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isWhitelistedEmail } from "@/lib/edge-config";
import { DATABASE_URL, conn } from "@/lib/planetscale";
import { conn } from "@/lib/planetscale";
import { ratelimit } from "@/lib/upstash";
import { ipAddress } from "@vercel/functions";
import { NextRequest, NextResponse } from "next/server";
Expand All @@ -15,12 +15,6 @@ export async function POST(req: NextRequest) {

const { email } = (await req.json()) as { email: string };

if (!DATABASE_URL) {
return new Response("Database connection not established", {
status: 500,
});
}

if (!process.env.NEXT_PUBLIC_IS_DUB) {
return NextResponse.json({ accountExists: true, hasPassword: true });
}
Expand Down
8 changes: 4 additions & 4 deletions apps/web/app/api/cron/import/csv/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addDomainToVercel, getDefaultDomains } from "@/lib/api/domains";
import { addDomainToVercel } from "@/lib/api/domains";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { bulkCreateLinks, createLink, processLink } from "@/lib/api/links";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
Expand All @@ -11,6 +11,7 @@ import { createLinkBodySchema } from "@/lib/zod/schemas/links";
import { randomBadgeColor } from "@/ui/links/tag-badge";
import {
DEFAULT_LINK_PROPS,
DUB_DOMAINS_ARRAY,
getPrettyUrl,
log,
parseDateTime,
Expand Down Expand Up @@ -69,7 +70,7 @@ export async function POST(req: Request) {

const response = await storage.fetch(url);

const [tags, domains, defaultDomains] = await Promise.all([
const [tags, domains] = await Promise.all([
prisma.tag.findMany({
where: { projectId: workspace.id },
select: { name: true },
Expand All @@ -78,7 +79,6 @@ export async function POST(req: Request) {
where: { projectId: workspace.id },
select: { slug: true },
}),
getDefaultDomains(workspace.id),
]);

const addedTags: string[] = [];
Expand Down Expand Up @@ -172,7 +172,7 @@ export async function POST(req: Request) {
const domainsNotInWorkspace = selectedDomains.filter(
(domain) =>
!domains?.find((d) => d.slug === domain) &&
!defaultDomains.find((d) => d === domain) &&
!DUB_DOMAINS_ARRAY.includes(domain) &&
!addedDomains.includes(domain),
);

Expand Down
3 changes: 3 additions & 0 deletions apps/web/app/api/domains/[domain]/primary/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export const POST = withWorkspace(
data: {
primary: true,
},
include: {
registeredDomain: true,
},
}),

// Set all other domains as not primary
Expand Down
5 changes: 5 additions & 0 deletions apps/web/app/api/domains/[domain]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const PATCH = withWorkspace(
slug: newDomain,
placeholder,
expiredUrl,
notFoundUrl,
archived,
} = updateDomainBodySchema.parse(await parseRequestBody(req));

Expand Down Expand Up @@ -88,8 +89,12 @@ export const PATCH = withWorkspace(
...(placeholder && { placeholder }),
...(workspace.plan != "free" && {
expiredUrl,
notFoundUrl,
}),
},
include: {
registeredDomain: true,
},
});

waitUntil(
Expand Down
45 changes: 38 additions & 7 deletions apps/web/app/api/domains/default/route.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
import { getDefaultDomains } from "@/lib/api/domains";
import { DubApiError } from "@/lib/api/errors";
import { withWorkspace } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import z from "@/lib/zod";
import { getDefaultDomainsQuerySchema } from "@/lib/zod/schemas/domains";
import { DUB_DOMAINS_ARRAY, getSearchParams } from "@dub/utils";
import { DUB_DOMAINS_ARRAY } from "@dub/utils";
import { NextResponse } from "next/server";

// GET /api/domains/default - get default domains
export const GET = withWorkspace(
async ({ req, workspace }) => {
const searchParams = getSearchParams(req.url);
async ({ workspace, searchParams }) => {
const { search } = getDefaultDomainsQuerySchema.parse(searchParams);
return NextResponse.json(await getDefaultDomains(workspace.id, { search }));

const data = await prisma.defaultDomains.findUnique({
where: {
projectId: workspace.id,
},
select: {
dubsh: true,
dublink: true,
chatgpt: true,
sptifi: true,
gitnew: true,
callink: true,
amznid: true,
ggllink: true,
figpage: true,
},
});

let defaultDomains: string[] = [];

if (data) {
defaultDomains = Object.keys(data)
.filter((key) => data[key])
.map(
(domain) =>
DUB_DOMAINS_ARRAY.find((d) => d.replace(".", "") === domain)!,
)
.filter((domain) =>
search ? domain?.toLowerCase().includes(search.toLowerCase()) : true,
);
}

return NextResponse.json(defaultDomains);
},
{
requiredPermissions: ["domains.read"],
Expand All @@ -23,8 +53,8 @@ const updateDefaultDomainsSchema = z.object({
defaultDomains: z.array(z.enum(DUB_DOMAINS_ARRAY as [string, ...string[]])),
});

// PUT /api/domains/default - edit default domains
export const PUT = withWorkspace(
// PATCH /api/domains/default - edit default domains
export const PATCH = withWorkspace(
async ({ req, workspace }) => {
const { defaultDomains } = await updateDefaultDomainsSchema.parseAsync(
await req.json(),
Expand All @@ -48,6 +78,7 @@ export const PUT = withWorkspace(
chatgpt: defaultDomains.includes("chatg.pt"),
sptifi: defaultDomains.includes("spti.fi"),
gitnew: defaultDomains.includes("git.new"),
callink: defaultDomains.includes("cal.link"),
amznid: defaultDomains.includes("amzn.id"),
ggllink: defaultDomains.includes("ggl.link"),
figpage: defaultDomains.includes("fig.page"),
Expand Down
63 changes: 50 additions & 13 deletions apps/web/app/api/domains/route.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import { addDomainToVercel, validateDomain } from "@/lib/api/domains";
import { DubApiError, exceededLimitError } from "@/lib/api/errors";
import { createLink } from "@/lib/api/links";
import { createLink, transformLink } from "@/lib/api/links";
import { parseRequestBody } from "@/lib/api/utils";
import { withWorkspace } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import {
DomainSchema,
createDomainBodySchema,
getDomainsQuerySchema,
getDomainsQuerySchemaExtended,
} from "@/lib/zod/schemas/domains";
import { DEFAULT_LINK_PROPS, getSearchParams } from "@dub/utils";
import { DEFAULT_LINK_PROPS } from "@dub/utils";
import { NextResponse } from "next/server";
import { z } from "zod";

// GET /api/domains – get all domains for a workspace
export const GET = withWorkspace(
async ({ req, workspace }) => {
const searchParams = getSearchParams(req.url);
const { search, archived, page, pageSize } =
getDomainsQuerySchema.parse(searchParams);
async ({ workspace, searchParams }) => {
const { search, archived, page, pageSize, includeLink } =
getDomainsQuerySchemaExtended.parse(searchParams);

const domains = await prisma.domain.findMany({
where: {
Expand All @@ -32,12 +30,43 @@ export const GET = withWorkspace(
},
include: {
registeredDomain: true,
...(includeLink && {
links: {
where: {
key: "_root",
},
include: {
tags: {
select: {
tag: {
select: {
id: true,
name: true,
color: true,
},
},
},
},
},
},
}),
},
take: pageSize,
skip: (page - 1) * pageSize,
});

return NextResponse.json(z.array(DomainSchema).parse(domains));
const response = domains.map((domain) => ({
...DomainSchema.parse(domain),
...(includeLink &&
domain.links.length > 0 && {
link: transformLink({
...domain.links[0],
tags: domain.links[0]["tags"].map((tag) => tag),
}),
}),
}));

return NextResponse.json(response);
},
{
requiredPermissions: ["domains.read"],
Expand All @@ -48,7 +77,7 @@ export const GET = withWorkspace(
export const POST = withWorkspace(
async ({ req, workspace, session }) => {
const body = await parseRequestBody(req);
const { slug, placeholder, expiredUrl } =
const { slug, placeholder, expiredUrl, notFoundUrl } =
createDomainBodySchema.parse(body);

const totalDomains = await prisma.domain.count({
Expand Down Expand Up @@ -103,9 +132,11 @@ export const POST = withWorkspace(
...(placeholder && { placeholder }),
...(workspace.plan !== "free" && {
expiredUrl,
notFoundUrl,
}),
},
}),

createLink({
...DEFAULT_LINK_PROPS,
domain: slug,
Expand All @@ -117,9 +148,15 @@ export const POST = withWorkspace(
}),
]);

return NextResponse.json(DomainSchema.parse(domainRecord), {
status: 201,
});
return NextResponse.json(
DomainSchema.parse({
...domainRecord,
registeredDomain: null,
}),
{
status: 201,
},
);
},
{
requiredPermissions: ["domains.write"],
Expand Down
Loading

0 comments on commit 98a78c7

Please sign in to comment.