From 038ffc8cbe86acb573f745290fc7f7cb14f8b879 Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Wed, 4 Dec 2024 02:02:14 +0100 Subject: [PATCH] refactor: move and rename fetchers, options --- src/actions/token.ts | 21 --------- src/app/(dashboard)/[guildUrlName]/actions.ts | 23 ++++------ .../[guildUrlName]/components/GuildTabs.tsx | 4 +- .../[guildUrlName]/components/JoinButton.tsx | 6 +-- src/app/(dashboard)/[guildUrlName]/layout.tsx | 2 +- src/app/(dashboard)/explorer/actions.ts | 5 +- .../explorer/components/GuildCard.tsx | 6 ++- src/app/(dashboard)/explorer/page.tsx | 13 ++++-- src/lib/fetchGuildApi.ts | 2 +- src/lib/fetchers.ts | 46 +++++++++++++++++++ .../[guildUrlName] => lib}/options.ts | 8 ++-- src/lib/resolveIdLikeRequest.ts | 6 +++ src/lib/token.ts | 21 +++++++++ src/v2/components/ui/Button.tsx | 0 14 files changed, 108 insertions(+), 55 deletions(-) create mode 100644 src/lib/fetchers.ts rename src/{app/(dashboard)/[guildUrlName] => lib}/options.ts (75%) create mode 100644 src/lib/resolveIdLikeRequest.ts create mode 100644 src/lib/token.ts create mode 100644 src/v2/components/ui/Button.tsx diff --git a/src/actions/token.ts b/src/actions/token.ts index 9fdb0dd6cd..e69de29bb2 100644 --- a/src/actions/token.ts +++ b/src/actions/token.ts @@ -1,21 +0,0 @@ -import { getTokenClientSide } from "@/lib/getCookieClientSide"; -import { tokenSchema } from "@/lib/schemas/user"; -import { isServer } from "@tanstack/react-query"; -import { jwtDecode } from "jwt-decode"; -import { getTokenServerSide } from "./auth"; - -export const tryGetToken = async () => { - const token = isServer ? await getTokenServerSide() : getTokenClientSide(); - - if (!token) { - throw new Error( - "Failed to retrieve JWT token on auth request initialization.", - ); - } - return token; -}; - -export const tryGetParsedToken = async () => { - const token = await tryGetToken(); - return tokenSchema.parse(jwtDecode(token)); -}; diff --git a/src/app/(dashboard)/[guildUrlName]/actions.ts b/src/app/(dashboard)/[guildUrlName]/actions.ts index 017785b412..5247218483 100644 --- a/src/app/(dashboard)/[guildUrlName]/actions.ts +++ b/src/app/(dashboard)/[guildUrlName]/actions.ts @@ -1,27 +1,22 @@ -import { tryGetParsedToken } from "@/actions/token"; import { fetchGuildApiData } from "@/lib/fetchGuildApi"; +import { resolveIdLikeRequest } from "@/lib/resolveIdLikeRequest"; +import { tryGetParsedToken } from "@/lib/token"; import type { ErrorLike, WithIdLike } from "@/lib/types"; import type { Schemas } from "@guildxyz/types"; -import z from "zod"; -const resolveIdLikeRequest = (idLike: string) => { - const isId = z.string().uuid().safeParse(idLike).success; - return `${isId ? "id" : "urlName"}/${idLike}`; -}; - -export const leaveGuild = async ({ guildId }: { guildId: string }) => { +export const fetchGuildLeave = async ({ guildId }: { guildId: string }) => { return fetchGuildApiData(`guild/${guildId}/leave`, { method: "POST", }); }; -export const getGuild = async ({ idLike }: WithIdLike) => { +export const fetchGuild = async ({ idLike }: WithIdLike) => { return fetchGuildApiData( `guild/${resolveIdLikeRequest(idLike)}`, ); }; -export const getEntity = async ({ +export const fetchEntity = async ({ idLike, entity, responseInit, @@ -34,16 +29,16 @@ export const getEntity = async ({ return fetchGuildApiData(pathname, responseInit); }; -export const getUser = async () => { +export const fetchUser = async () => { const { userId } = await tryGetParsedToken(); - return getEntity({ + return fetchEntity({ entity: "user", idLike: userId, }); }; -export const getPages = async ({ guildId }: { guildId: string }) => { - const guild = await getGuild({ idLike: guildId }); +export const fetchPages = async ({ guildId }: { guildId: string }) => { + const guild = await fetchGuild({ idLike: guildId }); return fetchGuildApiData("page/batch", { method: "POST", body: JSON.stringify({ ids: guild.pages?.map((p) => p.pageId!) ?? [] }), diff --git a/src/app/(dashboard)/[guildUrlName]/components/GuildTabs.tsx b/src/app/(dashboard)/[guildUrlName]/components/GuildTabs.tsx index 6038b8ee46..d4b918f9ac 100644 --- a/src/app/(dashboard)/[guildUrlName]/components/GuildTabs.tsx +++ b/src/app/(dashboard)/[guildUrlName]/components/GuildTabs.tsx @@ -2,12 +2,12 @@ import { Card } from "@/components/ui/Card"; import { ScrollArea, ScrollBar } from "@/components/ui/ScrollArea"; import { Skeleton } from "@/components/ui/Skeleton"; import { cn } from "@/lib/cssUtils"; +import { fetchPages } from "@/lib/fetchers"; import type { Schemas } from "@guildxyz/types"; -import { getPages } from "../actions"; import { PageNavLink } from "./RoleGroupNavLink"; export const GuildTabs = async ({ guild }: { guild: Schemas["GuildFull"] }) => { - const pages = await getPages({ guildId: guild.id }); + const pages = await fetchPages({ guildId: guild.id }); return ( { const { guildUrlName } = useParams<{ guildUrlName: string }>(); @@ -73,7 +73,7 @@ export const JoinButton = () => { }); const leaveMutation = useMutation({ - mutationFn: () => leaveGuild({ guildId: guild.data.id }), + mutationFn: () => fetchGuildLeave({ guildId: guild.data.id }), onSuccess: async () => { await queryClient.cancelQueries(userOptions()); const prev = queryClient.getQueryData(userOptions().queryKey); diff --git a/src/app/(dashboard)/[guildUrlName]/layout.tsx b/src/app/(dashboard)/[guildUrlName]/layout.tsx index ddabcabbad..bfce7733da 100644 --- a/src/app/(dashboard)/[guildUrlName]/layout.tsx +++ b/src/app/(dashboard)/[guildUrlName]/layout.tsx @@ -2,12 +2,12 @@ import { AuthBoundary } from "@/components/AuthBoundary"; import { GuildImage } from "@/components/GuildImage"; import { SignInButton } from "@/components/SignInButton"; import { getQueryClient } from "@/lib/getQueryClient"; +import { guildOptions, userOptions } from "@/lib/options"; import type { DynamicRoute } from "@/lib/types"; import { HydrationBoundary, dehydrate } from "@tanstack/react-query"; import { type PropsWithChildren, Suspense } from "react"; import { GuildTabs, GuildTabsSkeleton } from "./components/GuildTabs"; import { JoinButton } from "./components/JoinButton"; -import { guildOptions, userOptions } from "./options"; const GuildLayout = async ({ params, diff --git a/src/app/(dashboard)/explorer/actions.ts b/src/app/(dashboard)/explorer/actions.ts index 6e0334e3b4..0714e4e668 100644 --- a/src/app/(dashboard)/explorer/actions.ts +++ b/src/app/(dashboard)/explorer/actions.ts @@ -1,14 +1,13 @@ -"use server"; import { fetchGuildApiData } from "@/lib/fetchGuildApi"; -import type { Guild } from "@/lib/schemas/guild"; import type { PaginatedResponse } from "@/lib/types"; +import type { Schemas } from "@guildxyz/types"; import { PAGE_SIZE } from "./constants"; export const getGuildSearch = async ({ pageParam, search, }: { pageParam: number; search: string }) => { - return fetchGuildApiData>( + return fetchGuildApiData>( `guild/search?page=${pageParam}&pageSize=${PAGE_SIZE}&search=${search}`, ); }; diff --git a/src/app/(dashboard)/explorer/components/GuildCard.tsx b/src/app/(dashboard)/explorer/components/GuildCard.tsx index 911eba4937..344e8d60a9 100644 --- a/src/app/(dashboard)/explorer/components/GuildCard.tsx +++ b/src/app/(dashboard)/explorer/components/GuildCard.tsx @@ -2,13 +2,15 @@ import { GuildImage } from "@/components/GuildImage"; import { Badge } from "@/components/ui/Badge"; import { Card } from "@/components/ui/Card"; import { Skeleton } from "@/components/ui/Skeleton"; -import type { Guild } from "@/lib/schemas/guild"; +import type { Schemas } from "@guildxyz/types"; import { Users } from "@phosphor-icons/react/dist/ssr"; import Link from "next/link"; import type { FunctionComponent } from "react"; -export const GuildCard: FunctionComponent<{ guild: Guild }> = ({ guild }) => { +export const GuildCard: FunctionComponent<{ guild: Schemas["GuildFull"] }> = ({ + guild, +}) => { return ( { const { userId } = await tryGetParsedToken(); - return fetchGuildApiData>( + return fetchGuildApiData>( `guild/search?page=1&pageSize=${Number.MAX_SAFE_INTEGER}&sortBy=name&reverse=false&customQuery=@owner:{${userId}}`, ); }; @@ -108,7 +108,12 @@ async function AssociatedGuildsSection() { } async function AssociatedGuilds() { - const { items: associatedGuilds } = await getAssociatedGuilds(); + let associatedGuilds: Schemas["GuildFull"][]; + try { + associatedGuilds = (await getAssociatedGuilds()).items; + } catch { + return; + } return associatedGuilds.length > 0 ? (
diff --git a/src/lib/fetchGuildApi.ts b/src/lib/fetchGuildApi.ts index 4b70fadc1c..b34565dedb 100644 --- a/src/lib/fetchGuildApi.ts +++ b/src/lib/fetchGuildApi.ts @@ -1,4 +1,4 @@ -import { tryGetToken } from "@/actions/token"; +import { tryGetToken } from "@/lib/token"; import { env } from "./env"; import type { ErrorLike } from "./types"; diff --git a/src/lib/fetchers.ts b/src/lib/fetchers.ts new file mode 100644 index 0000000000..5247218483 --- /dev/null +++ b/src/lib/fetchers.ts @@ -0,0 +1,46 @@ +import { fetchGuildApiData } from "@/lib/fetchGuildApi"; +import { resolveIdLikeRequest } from "@/lib/resolveIdLikeRequest"; +import { tryGetParsedToken } from "@/lib/token"; +import type { ErrorLike, WithIdLike } from "@/lib/types"; +import type { Schemas } from "@guildxyz/types"; + +export const fetchGuildLeave = async ({ guildId }: { guildId: string }) => { + return fetchGuildApiData(`guild/${guildId}/leave`, { + method: "POST", + }); +}; + +export const fetchGuild = async ({ idLike }: WithIdLike) => { + return fetchGuildApiData( + `guild/${resolveIdLikeRequest(idLike)}`, + ); +}; + +export const fetchEntity = async ({ + idLike, + entity, + responseInit, +}: { + entity: string; + idLike: string; + responseInit?: Parameters[1]; +}) => { + const pathname = `${entity}/${resolveIdLikeRequest(idLike)}`; + return fetchGuildApiData(pathname, responseInit); +}; + +export const fetchUser = async () => { + const { userId } = await tryGetParsedToken(); + return fetchEntity({ + entity: "user", + idLike: userId, + }); +}; + +export const fetchPages = async ({ guildId }: { guildId: string }) => { + const guild = await fetchGuild({ idLike: guildId }); + return fetchGuildApiData("page/batch", { + method: "POST", + body: JSON.stringify({ ids: guild.pages?.map((p) => p.pageId!) ?? [] }), + }); +}; diff --git a/src/app/(dashboard)/[guildUrlName]/options.ts b/src/lib/options.ts similarity index 75% rename from src/app/(dashboard)/[guildUrlName]/options.ts rename to src/lib/options.ts index 9cc252fa29..1901a057d0 100644 --- a/src/app/(dashboard)/[guildUrlName]/options.ts +++ b/src/lib/options.ts @@ -1,16 +1,16 @@ +import { fetchEntity, fetchUser } from "@/lib/fetchers"; import type { ErrorLike } from "@/lib/types"; import type { Schemas } from "@guildxyz/types"; import { queryOptions } from "@tanstack/react-query"; -import { getEntity, getUser } from "./actions"; export const entityOptions = ({ entity, idLike, ...rest -}: Parameters[0]) => { +}: Parameters[0]) => { return queryOptions({ queryKey: [entity, idLike], - queryFn: () => getEntity({ entity, idLike, ...rest }), + queryFn: () => fetchEntity({ entity, idLike, ...rest }), }); }; @@ -24,6 +24,6 @@ export const guildOptions = ({ idLike }: { idLike: string }) => { export const userOptions = () => { return queryOptions({ queryKey: ["user"], - queryFn: () => getUser(), + queryFn: () => fetchUser(), }); }; diff --git a/src/lib/resolveIdLikeRequest.ts b/src/lib/resolveIdLikeRequest.ts new file mode 100644 index 0000000000..46cc0d4c38 --- /dev/null +++ b/src/lib/resolveIdLikeRequest.ts @@ -0,0 +1,6 @@ +import z from "zod"; + +export const resolveIdLikeRequest = (idLike: string) => { + const isId = z.string().uuid().safeParse(idLike).success; + return `${isId ? "id" : "urlName"}/${idLike}`; +}; diff --git a/src/lib/token.ts b/src/lib/token.ts new file mode 100644 index 0000000000..0c144c08c5 --- /dev/null +++ b/src/lib/token.ts @@ -0,0 +1,21 @@ +import { getTokenServerSide } from "@/actions/auth"; +import { getTokenClientSide } from "@/lib/getCookieClientSide"; +import { tokenSchema } from "@/lib/schemas/user"; +import { isServer } from "@tanstack/react-query"; +import { jwtDecode } from "jwt-decode"; + +export const tryGetToken = async () => { + const token = isServer ? await getTokenServerSide() : getTokenClientSide(); + + if (!token) { + throw new Error( + "Failed to retrieve JWT token on auth request initialization.", + ); + } + return token; +}; + +export const tryGetParsedToken = async () => { + const token = await tryGetToken(); + return tokenSchema.parse(jwtDecode(token)); +}; diff --git a/src/v2/components/ui/Button.tsx b/src/v2/components/ui/Button.tsx new file mode 100644 index 0000000000..e69de29bb2