From 99a7feb64b4f0b0fd8a35d2b83d424a263580cd7 Mon Sep 17 00:00:00 2001 From: Arpit Gupta Date: Fri, 24 Apr 2026 01:28:44 +0530 Subject: [PATCH] feat(chat): migrate GET /api/accounts/{id}/catalogs (#1691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: migrate getCatalogs to GET /api/accounts/{id}/catalogs Repoints the chat caller off the legacy Agent API host onto the new nested route on recoup-api.vercel.app. Adds Privy Bearer auth and threads the access token through useCatalogs. * fix: gate useCatalogs on auth readiness Add `authenticated` from usePrivy() to the query's `enabled` flag so the request doesn't fire with an empty Bearer token before Privy resolves. Matches the canonical pattern in useAccountOrganizations.ts / useSandboxes.ts. Note: pnpm lint / typecheck not run — node_modules missing in worktree. Co-Authored-By: Claude Opus 4.7 --------- Co-authored-by: Claude Opus 4.7 --- hooks/useCatalogs.ts | 10 ++++++++-- lib/catalog/getCatalogs.ts | 21 +++++++++++++++------ types/Catalog.ts | 6 ++++++ 3 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 types/Catalog.ts diff --git a/hooks/useCatalogs.ts b/hooks/useCatalogs.ts index b5c3a4085..2e89aa0bc 100644 --- a/hooks/useCatalogs.ts +++ b/hooks/useCatalogs.ts @@ -1,15 +1,21 @@ import { useQuery, UseQueryResult } from "@tanstack/react-query"; +import { usePrivy } from "@privy-io/react-auth"; import { getCatalogs, CatalogsResponse } from "@/lib/catalog/getCatalogs"; import { useUserProvider } from "@/providers/UserProvder"; const useCatalogs = (): UseQueryResult => { + const { getAccessToken, authenticated } = usePrivy(); const { userData } = useUserProvider(); const accountId = userData?.account_id || ""; return useQuery({ queryKey: ["catalogs", accountId], - queryFn: () => getCatalogs(accountId), - enabled: !!accountId, + queryFn: async () => { + const accessToken = await getAccessToken(); + if (!accessToken) throw new Error("No access token"); + return getCatalogs(accountId, accessToken); + }, + enabled: !!accountId && authenticated, staleTime: 5 * 60 * 1000, // 5 minutes refetchOnWindowFocus: false, }); diff --git a/lib/catalog/getCatalogs.ts b/lib/catalog/getCatalogs.ts index 179d1f3a9..8eaf750c6 100644 --- a/lib/catalog/getCatalogs.ts +++ b/lib/catalog/getCatalogs.ts @@ -1,6 +1,5 @@ -import { Tables } from "@/types/database.types"; - -type Catalog = Tables<"catalogs">; +import { getClientApiBaseUrl } from "@/lib/api/getClientApiBaseUrl"; +import type { Catalog } from "@/types/Catalog"; export interface CatalogsResponse { status: string; @@ -8,18 +7,28 @@ export interface CatalogsResponse { error?: string; } +/** + * Fetches catalogs linked to an account from the Recoup API. + * + * Authentication is via Bearer token (Privy access token). + * + * @param accountId - The account id whose catalogs to fetch (path segment). + * @param accessToken - Privy access token for Bearer auth. + */ export async function getCatalogs( - accountId: string + accountId: string, + accessToken: string, ): Promise { try { const response = await fetch( - `https://api.recoupable.com/api/catalogs?account_id=${accountId}`, + `${getClientApiBaseUrl()}/api/accounts/${accountId}/catalogs`, { method: "GET", headers: { "Content-Type": "application/json", + Authorization: `Bearer ${accessToken}`, }, - } + }, ); if (!response.ok) { diff --git a/types/Catalog.ts b/types/Catalog.ts new file mode 100644 index 000000000..aeea342d8 --- /dev/null +++ b/types/Catalog.ts @@ -0,0 +1,6 @@ +export interface Catalog { + id: string; + name: string; + created_at: string; + updated_at: string; +}