diff --git a/surfsense_web/app/dashboard/[search_space_id]/podcasts/podcasts-client.tsx b/surfsense_web/app/dashboard/[search_space_id]/podcasts/podcasts-client.tsx index 9f0a7be29..535524b8e 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/podcasts/podcasts-client.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/podcasts/podcasts-client.tsx @@ -6,7 +6,7 @@ import { MoreHorizontal, Pause, Play, - Podcast, + Podcast as PodcastIcon, Search, SkipBack, SkipForward, @@ -46,16 +46,8 @@ import { SelectValue, } from "@/components/ui/select"; import { Slider } from "@/components/ui/slider"; - -export interface PodcastItem { - id: number; - title: string; - created_at: string; - file_location: string; - podcast_transcript: any[]; - search_space_id: number; - chat_state_version: number | null; -} +import type { Podcast } from "@/contracts/types/podcast.types"; +import { podcastsApiService } from "@/lib/apis/podcasts-api.service"; interface PodcastsPageClientProps { searchSpaceId: string; @@ -85,8 +77,8 @@ const podcastCardVariants: Variants = { const MotionCard = motion(Card); export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClientProps) { - const [podcasts, setPodcasts] = useState([]); - const [filteredPodcasts, setFilteredPodcasts] = useState([]); + const [podcasts, setPodcasts] = useState([]); + const [filteredPodcasts, setFilteredPodcasts] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [searchQuery, setSearchQuery] = useState(""); @@ -99,7 +91,7 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient const [isDeleting, setIsDeleting] = useState(false); // Audio player state - const [currentPodcast, setCurrentPodcast] = useState(null); + const [currentPodcast, setCurrentPodcast] = useState(null); const [audioSrc, setAudioSrc] = useState(undefined); const [isAudioLoading, setIsAudioLoading] = useState(false); const [isPlaying, setIsPlaying] = useState(false); @@ -148,7 +140,7 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient ); } - const data: PodcastItem[] = await response.json(); + const data: Podcast[] = await response.json(); setPodcasts(data); setFilteredPodcasts(data); setError(null); @@ -305,7 +297,7 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient }; // Play podcast - Fetch blob and set object URL - const playPodcast = async (podcast: PodcastItem) => { + const playPodcast = async (podcast: Podcast) => { // If the same podcast is selected, just toggle play/pause if (currentPodcast && currentPodcast.id === podcast.id) { togglePlayPause(); @@ -326,11 +318,6 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient setIsPlaying(false); setIsAudioLoading(true); - const token = localStorage.getItem("surfsense_bearer_token"); - if (!token) { - throw new Error("Authentication token not found."); - } - // Revoke previous object URL if exists (only after we've started the new request) if (currentObjectUrlRef.current) { URL.revokeObjectURL(currentObjectUrlRef.current); @@ -342,22 +329,11 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout try { - const response = await fetch( - `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/podcasts/${podcast.id}/stream`, - { - headers: { - Authorization: `Bearer ${token}`, - }, - signal: controller.signal, - } - ); - - if (!response.ok) { - throw new Error(`Failed to fetch audio stream: ${response.statusText}`); - } - - const blob = await response.blob(); - const objectUrl = URL.createObjectURL(blob); + const response = await podcastsApiService.loadPodcast({ + podcast, + controller, + }); + const objectUrl = URL.createObjectURL(response); currentObjectUrlRef.current = objectUrl; // Set audio source @@ -501,7 +477,7 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient {!isLoading && !error && filteredPodcasts.length === 0 && (
- +

No podcasts found

{searchQuery @@ -829,7 +805,7 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient duration: 2, }} > - +

diff --git a/surfsense_web/atoms/chats/chat-mutation.atoms.ts b/surfsense_web/atoms/chats/chat-mutation.atoms.ts index da0795afa..cca69fdce 100644 --- a/surfsense_web/atoms/chats/chat-mutation.atoms.ts +++ b/surfsense_web/atoms/chats/chat-mutation.atoms.ts @@ -1,7 +1,7 @@ import { atomWithMutation } from "jotai-tanstack-query"; import { toast } from "sonner"; import type { Chat } from "@/app/dashboard/[search_space_id]/chats/chats-client"; -import { chatApiService } from "@/lib/apis/chats-api.service"; +import { chatsApiService } from "@/lib/apis/chats-api.service"; import { cacheKeys } from "@/lib/query-client/cache-keys"; import { queryClient } from "@/lib/query-client/client"; import { activeSearchSpaceIdAtom } from "../seach-spaces/seach-space-queries.atom"; @@ -14,7 +14,7 @@ export const deleteChatMutationAtom = atomWithMutation((get) => { mutationKey: cacheKeys.activeSearchSpace.chats(searchSpaceId ?? ""), enabled: !!searchSpaceId && !!authToken, mutationFn: async (chatId: number) => { - return chatApiService.deleteChat({ id: chatId }); + return chatsApiService.deleteChat({ id: chatId }); }, onSuccess: (_, chatId) => { diff --git a/surfsense_web/atoms/chats/chat-querie.atoms.ts b/surfsense_web/atoms/chats/chat-querie.atoms.ts index 8ea668eb4..c0269d9b7 100644 --- a/surfsense_web/atoms/chats/chat-querie.atoms.ts +++ b/surfsense_web/atoms/chats/chat-querie.atoms.ts @@ -1,16 +1,16 @@ import { atom } from "jotai"; import { atomWithQuery } from "jotai-tanstack-query"; import type { ChatDetails } from "@/app/dashboard/[search_space_id]/chats/chats-client"; -import type { PodcastItem } from "@/app/dashboard/[search_space_id]/podcasts/podcasts-client"; import { activeSearchSpaceIdAtom } from "@/atoms/seach-spaces/seach-space-queries.atom"; -import { chatApiService } from "@/lib/apis/chats-api.service"; -import { getPodcastByChatId } from "@/lib/apis/podcasts.api"; +import type { Podcast } from "@/contracts/types/podcast.types"; +import { chatsApiService } from "@/lib/apis/chats-api.service"; +import { podcastsApiService } from "@/lib/apis/podcasts-api.service"; import { cacheKeys } from "@/lib/query-client/cache-keys"; type ActiveChatState = { chatId: string | null; chatDetails: ChatDetails | null; - podcast: PodcastItem | null; + podcast: Podcast | null; }; export const activeChatIdAtom = atom(null); @@ -31,8 +31,8 @@ export const activeChatAtom = atomWithQuery((get) => { } const [podcast, chatDetails] = await Promise.all([ - getPodcastByChatId(activeChatId, authToken), - chatApiService.getChatDetails({ id: Number(activeChatId) }), + podcastsApiService.getPodcastByChatId({ chat_id: Number(activeChatId) }), + chatsApiService.getChatDetails({ id: Number(activeChatId) }), ]); return { chatId: activeChatId, chatDetails, podcast }; @@ -48,7 +48,7 @@ export const activeSearchSpaceChatsAtom = atomWithQuery((get) => { queryKey: cacheKeys.activeSearchSpace.chats(searchSpaceId ?? ""), enabled: !!searchSpaceId && !!authToken, queryFn: async () => { - return chatApiService.getChatsBySearchSpace({ search_space_id: Number(searchSpaceId) }); + return chatsApiService.getChatsBySearchSpace({ search_space_id: Number(searchSpaceId) }); }, }; }); diff --git a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx index 3edd00400..1c62d070d 100644 --- a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx +++ b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx @@ -4,18 +4,11 @@ import { LoaderIcon, PanelRight, TriangleAlert } from "lucide-react"; import { toast } from "sonner"; import { activeChatAtom, activeChatIdAtom } from "@/atoms/chats/chat-querie.atoms"; import { activeChathatUIAtom } from "@/atoms/chats/ui.atoms"; -import { generatePodcast } from "@/lib/apis/podcasts.api"; +import type { GeneratePodcastRequest } from "@/contracts/types/podcast.types"; +import { podcastsApiService } from "@/lib/apis/podcasts-api.service"; import { cn } from "@/lib/utils"; import { ChatPanelView } from "./ChatPanelView"; -export interface GeneratePodcastRequest { - type: "CHAT" | "DOCUMENT"; - ids: number[]; - search_space_id: number; - podcast_title?: string; - user_prompt?: string; -} - export function ChatPanelContainer() { const { data: activeChatState, @@ -31,7 +24,7 @@ export function ChatPanelContainer() { if (!authToken) { throw new Error("Authentication error. Please log in again."); } - await generatePodcast(request, authToken); + await podcastsApiService.generatePodcast(request); toast.success(`Podcast generation started!`); } catch (error) { toast.error("Error generating podcast. Please log in again."); diff --git a/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx b/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx index f789ab848..bde6fc5d7 100644 --- a/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx +++ b/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx @@ -1,16 +1,17 @@ "use client"; -import { Pause, Play, Podcast, SkipBack, SkipForward, Volume2, VolumeX, X } from "lucide-react"; +import { Pause, Play, SkipBack, SkipForward, Volume2, VolumeX, X } from "lucide-react"; import { motion } from "motion/react"; import { useEffect, useRef, useState } from "react"; import { toast } from "sonner"; -import type { PodcastItem } from "@/app/dashboard/[search_space_id]/podcasts/podcasts-client"; import { Button } from "@/components/ui/button"; import { Slider } from "@/components/ui/slider"; +import type { Podcast } from "@/contracts/types/podcast.types"; +import { podcastsApiService } from "@/lib/apis/podcasts-api.service"; import { PodcastPlayerCompactSkeleton } from "./PodcastPlayerCompactSkeleton"; interface PodcastPlayerProps { - podcast: PodcastItem | null; + podcast: Podcast | null; isLoading?: boolean; onClose?: () => void; compact?: boolean; @@ -56,11 +57,6 @@ export function PodcastPlayer({ const loadPodcast = async () => { setIsFetching(true); try { - const token = localStorage.getItem("surfsense_bearer_token"); - if (!token) { - throw new Error("Authentication token not found."); - } - // Revoke previous object URL if exists if (currentObjectUrlRef.current) { URL.revokeObjectURL(currentObjectUrlRef.current); @@ -71,22 +67,12 @@ export function PodcastPlayer({ const timeoutId = setTimeout(() => controller.abort(), 30000); try { - const response = await fetch( - `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/podcasts/${podcast.id}/stream`, - { - headers: { - Authorization: `Bearer ${token}`, - }, - signal: controller.signal, - } - ); + const response = await podcastsApiService.loadPodcast({ + podcast, + controller, + }); - if (!response.ok) { - throw new Error(`Failed to fetch audio stream: ${response.statusText}`); - } - - const blob = await response.blob(); - const objectUrl = URL.createObjectURL(blob); + const objectUrl = URL.createObjectURL(response); currentObjectUrlRef.current = objectUrl; setAudioSrc(objectUrl); } catch (error) { diff --git a/surfsense_web/contracts/types/podcast.types.ts b/surfsense_web/contracts/types/podcast.types.ts index a1e091214..c037ff43e 100644 --- a/surfsense_web/contracts/types/podcast.types.ts +++ b/surfsense_web/contracts/types/podcast.types.ts @@ -1,29 +1,27 @@ import { z } from "zod"; export const podcast = z.object({ - id: z.number(), - title: z.string(), - created_at: z.string(), - file_location: z.string(), - podcast_transcript: z.array(z.any()), - search_space_id: z.number(), - chat_state_version: z.number().nullable(), + id: z.number(), + title: z.string(), + created_at: z.string(), + file_location: z.string(), + podcast_transcript: z.array(z.any()), + search_space_id: z.number(), + chat_state_version: z.number().nullable(), }); export const generatePodcastRequest = z.object({ - type: z.enum(["CHAT", "DOCUMENT"]), - ids: z.array(z.number()), - search_space_id: z.number(), - podcast_title: z.string().optional(), - user_prompt: z.string().optional(), + type: z.enum(["CHAT", "DOCUMENT"]), + ids: z.array(z.number()), + search_space_id: z.number(), + podcast_title: z.string().optional(), + user_prompt: z.string().optional(), }); export const getPodcastByChatIdRequest = z.object({ - chat_id: z.number(), + chat_id: z.number(), }); export type GeneratePodcastRequest = z.infer; -export type GetPodcastByChatIdRequest = z.infer< - typeof getPodcastByChatIdRequest ->; +export type GetPodcastByChatIdRequest = z.infer; export type Podcast = z.infer; diff --git a/surfsense_web/lib/apis/auth-api.service.ts b/surfsense_web/lib/apis/auth-api.service.ts index 40d496354..e2be8c860 100644 --- a/surfsense_web/lib/apis/auth-api.service.ts +++ b/surfsense_web/lib/apis/auth-api.service.ts @@ -9,7 +9,7 @@ import { import { ValidationError } from "../error"; import { baseApiService } from "./base-api.service"; - class AuthApiService { +class AuthApiService { login = async (request: LoginRequest) => { // Validate the request const parsedRequest = loginRequest.safeParse(request); diff --git a/surfsense_web/lib/apis/base-api.service.ts b/surfsense_web/lib/apis/base-api.service.ts index 0d59a640a..e396364ec 100644 --- a/surfsense_web/lib/apis/base-api.service.ts +++ b/surfsense_web/lib/apis/base-api.service.ts @@ -1,264 +1,232 @@ import type z from "zod"; -import { - AppError, - AuthenticationError, - AuthorizationError, - NotFoundError, -} from "../error"; +import { AppError, AuthenticationError, AuthorizationError, NotFoundError } from "../error"; enum ResponseType { - JSON = "json", - TEXT = "text", - BLOB = "blob", - ARRAY_BUFFER = "arrayBuffer", - // Add more response types as needed + JSON = "json", + TEXT = "text", + BLOB = "blob", + ARRAY_BUFFER = "arrayBuffer", + // Add more response types as needed } export type RequestOptions = { - method: "GET" | "POST" | "PUT" | "DELETE"; - headers?: Record; - contentType?: "application/json" | "application/x-www-form-urlencoded"; - signal?: AbortSignal; - body?: any; - responseType?: ResponseType; - // Add more options as needed + method: "GET" | "POST" | "PUT" | "DELETE"; + headers?: Record; + contentType?: "application/json" | "application/x-www-form-urlencoded"; + signal?: AbortSignal; + body?: any; + responseType?: ResponseType; + // Add more options as needed }; class BaseApiService { - bearerToken: string; - baseUrl: string; + bearerToken: string; + baseUrl: string; - noAuthEndpoints: string[] = [ - "/auth/jwt/login", - "/auth/register", - "/auth/refresh", - ]; // Add more endpoints as needed + noAuthEndpoints: string[] = ["/auth/jwt/login", "/auth/register", "/auth/refresh"]; // Add more endpoints as needed - constructor(bearerToken: string, baseUrl: string) { - this.bearerToken = bearerToken; - this.baseUrl = baseUrl; - } + constructor(bearerToken: string, baseUrl: string) { + this.bearerToken = bearerToken; + this.baseUrl = baseUrl; + } - setBearerToken(bearerToken: string) { - this.bearerToken = bearerToken; - } + setBearerToken(bearerToken: string) { + this.bearerToken = bearerToken; + } - async request( - url: string, - responseSchema?: z.ZodSchema, - options?: RequestOptions & { responseType?: R } - ): Promise< - R extends ResponseType.JSON - ? T - : R extends ResponseType.TEXT - ? string - : R extends ResponseType.BLOB - ? Blob - : R extends ResponseType.ARRAY_BUFFER - ? ArrayBuffer - : unknown - > { - try { - const defaultOptions: RequestOptions = { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${this.bearerToken || ""}`, - }, - method: "GET", - responseType: ResponseType.JSON, - }; + async request( + url: string, + responseSchema?: z.ZodSchema, + options?: RequestOptions & { responseType?: R } + ): Promise< + R extends ResponseType.JSON + ? T + : R extends ResponseType.TEXT + ? string + : R extends ResponseType.BLOB + ? Blob + : R extends ResponseType.ARRAY_BUFFER + ? ArrayBuffer + : unknown + > { + try { + const defaultOptions: RequestOptions = { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${this.bearerToken || ""}`, + }, + method: "GET", + responseType: ResponseType.JSON, + }; - const mergedOptions: RequestOptions = { - ...defaultOptions, - ...(options ?? {}), - headers: { - ...defaultOptions.headers, - ...(options?.headers ?? {}), - }, - }; + const mergedOptions: RequestOptions = { + ...defaultOptions, + ...(options ?? {}), + headers: { + ...defaultOptions.headers, + ...(options?.headers ?? {}), + }, + }; - if (!this.baseUrl) { - throw new AppError("Base URL is not set."); - } + if (!this.baseUrl) { + throw new AppError("Base URL is not set."); + } - if (!this.bearerToken && !this.noAuthEndpoints.includes(url)) { - throw new AuthenticationError( - "You are not authenticated. Please login again." - ); - } + if (!this.bearerToken && !this.noAuthEndpoints.includes(url)) { + throw new AuthenticationError("You are not authenticated. Please login again."); + } - const fullUrl = new URL(url, this.baseUrl).toString(); + const fullUrl = new URL(url, this.baseUrl).toString(); - const response = await fetch(fullUrl, mergedOptions); + const response = await fetch(fullUrl, mergedOptions); - if (!response.ok) { - // biome-ignore lint/suspicious: Unknown - let data; + if (!response.ok) { + // biome-ignore lint/suspicious: Unknown + let data; - try { - data = await response.json(); - } catch (error) { - console.error("Failed to parse response as JSON:", error); + try { + data = await response.json(); + } catch (error) { + console.error("Failed to parse response as JSON:", error); - throw new AppError( - "Something went wrong", - response.status, - response.statusText - ); - } + throw new AppError("Something went wrong", response.status, response.statusText); + } - // for fastapi errors response - if (typeof data === "object" && "detail" in data) { - throw new AppError(data.detail, response.status, response.statusText); - } + // for fastapi errors response + if (typeof data === "object" && "detail" in data) { + throw new AppError(data.detail, response.status, response.statusText); + } - switch (response.status) { - case 401: - throw new AuthenticationError( - "You are not authenticated. Please login again.", - response.status, - response.statusText - ); - case 403: - throw new AuthorizationError( - "You don't have permission to access this resource.", - response.status, - response.statusText - ); - case 404: - throw new NotFoundError( - "Resource not found", - response.status, - response.statusText - ); - // Add more cases as needed - default: - throw new AppError( - "Something went wrong", - response.status, - response.statusText - ); - } - } + switch (response.status) { + case 401: + throw new AuthenticationError( + "You are not authenticated. Please login again.", + response.status, + response.statusText + ); + case 403: + throw new AuthorizationError( + "You don't have permission to access this resource.", + response.status, + response.statusText + ); + case 404: + throw new NotFoundError("Resource not found", response.status, response.statusText); + // Add more cases as needed + default: + throw new AppError("Something went wrong", response.status, response.statusText); + } + } - // biome-ignore lint/suspicious: Unknown - let data; - const responseType = mergedOptions.responseType + // biome-ignore lint/suspicious: Unknown + let data; + const responseType = mergedOptions.responseType; - try { - switch (responseType) { - case ResponseType.JSON: - data = await response.json(); - break; - case ResponseType.TEXT: - data = await response.text(); - break; - case ResponseType.BLOB: - data = await response.blob(); - break; - case ResponseType.ARRAY_BUFFER: - data = await response.arrayBuffer(); - break; - // Add more cases as needed - default: - data = await response.text(); - } - } catch (error) { - console.error("Failed to parse response as JSON:", error); - throw new AppError( - "Failed to parse response", - response.status, - response.statusText - ); - } + try { + switch (responseType) { + case ResponseType.JSON: + data = await response.json(); + break; + case ResponseType.TEXT: + data = await response.text(); + break; + case ResponseType.BLOB: + data = await response.blob(); + break; + case ResponseType.ARRAY_BUFFER: + data = await response.arrayBuffer(); + break; + // Add more cases as needed + default: + data = await response.text(); + } + } catch (error) { + console.error("Failed to parse response as JSON:", error); + throw new AppError("Failed to parse response", response.status, response.statusText); + } - if (responseType === ResponseType.JSON) { - if (!responseSchema) { - return data; - } - const parsedData = responseSchema.safeParse(data); + if (responseType === ResponseType.JSON) { + if (!responseSchema) { + return data; + } + const parsedData = responseSchema.safeParse(data); - if (!parsedData.success) { - /** The request was successful, but the response data does not match the expected schema. - * This is a client side error, and should be fixed by updating the responseSchema to keep things typed. - * This error should not be shown to the user , it is for dev only. - */ - console.error("Invalid API response schema:", parsedData.error); - } + if (!parsedData.success) { + /** The request was successful, but the response data does not match the expected schema. + * This is a client side error, and should be fixed by updating the responseSchema to keep things typed. + * This error should not be shown to the user , it is for dev only. + */ + console.error("Invalid API response schema:", parsedData.error); + } - return data; - } + return data; + } - return data; - } catch (error) { - console.error("Request failed:", error); - throw error; - } - } + return data; + } catch (error) { + console.error("Request failed:", error); + throw error; + } + } - async get( - url: string, - responseSchema?: z.ZodSchema, - options?: Omit - ) { - return this.request(url, responseSchema, { - ...options, - method: "GET", - responseType: ResponseType.JSON, - }); - } + async get( + url: string, + responseSchema?: z.ZodSchema, + options?: Omit + ) { + return this.request(url, responseSchema, { + ...options, + method: "GET", + responseType: ResponseType.JSON, + }); + } - async post( - url: string, - responseSchema?: z.ZodSchema, - options?: Omit - ) { - return this.request(url, responseSchema, { - method: "POST", - ...options, - responseType: ResponseType.JSON, - }); - } + async post( + url: string, + responseSchema?: z.ZodSchema, + options?: Omit + ) { + return this.request(url, responseSchema, { + method: "POST", + ...options, + responseType: ResponseType.JSON, + }); + } - async put( - url: string, - responseSchema?: z.ZodSchema, - options?: Omit - ) { - return this.request(url, responseSchema, { - method: "PUT", - ...options, - responseType: ResponseType.JSON, - }); - } + async put( + url: string, + responseSchema?: z.ZodSchema, + options?: Omit + ) { + return this.request(url, responseSchema, { + method: "PUT", + ...options, + responseType: ResponseType.JSON, + }); + } - async delete( - url: string, - responseSchema?: z.ZodSchema, - options?: Omit, - ) { - return this.request(url, responseSchema, { - method: "DELETE", - ...options, - responseType: ResponseType.JSON, - }); - } + async delete( + url: string, + responseSchema?: z.ZodSchema, + options?: Omit + ) { + return this.request(url, responseSchema, { + method: "DELETE", + ...options, + responseType: ResponseType.JSON, + }); + } - async getBlob( - url: string, - options?: Omit - ) { - return this.request(url, undefined, { - ...options, - method: "GET", - responseType: ResponseType.BLOB, - }); - } + async getBlob(url: string, options?: Omit) { + return this.request(url, undefined, { + ...options, + method: "GET", + responseType: ResponseType.BLOB, + }); + } } export const baseApiService = new BaseApiService( - typeof window !== "undefined" - ? localStorage.getItem("surfsense_bearer_token") || "" - : "", - process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "" + typeof window !== "undefined" ? localStorage.getItem("surfsense_bearer_token") || "" : "", + process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "" ); diff --git a/surfsense_web/lib/apis/chats-api.service.ts b/surfsense_web/lib/apis/chats-api.service.ts index d6d309106..498c99ef1 100644 --- a/surfsense_web/lib/apis/chats-api.service.ts +++ b/surfsense_web/lib/apis/chats-api.service.ts @@ -17,7 +17,7 @@ import { import { ValidationError } from "../error"; import { baseApiService } from "./base-api.service"; - class ChatApiService { +class ChatApiService { getChatDetails = async (request: GetChatDetailsRequest) => { // Validate the request const parsedRequest = getChatDetailsRequest.safeParse(request); diff --git a/surfsense_web/lib/apis/podcasts-api.service.ts b/surfsense_web/lib/apis/podcasts-api.service.ts index 336dd35cc..2142dc6e6 100644 --- a/surfsense_web/lib/apis/podcasts-api.service.ts +++ b/surfsense_web/lib/apis/podcasts-api.service.ts @@ -1,68 +1,58 @@ -import { baseApiService } from "./base-api.service"; import { - GeneratePodcastRequest, - generatePodcastRequest, - getPodcastByChatIdRequest, - GetPodcastByChatIdRequest, - Podcast, - podcast, + type GeneratePodcastRequest, + type GetPodcastByChatIdRequest, + generatePodcastRequest, + getPodcastByChatIdRequest, + type Podcast, + podcast, } from "@/contracts/types/podcast.types"; import { ValidationError } from "../error"; +import { baseApiService } from "./base-api.service"; class PodcastsApiService { - getPodcastByChatId = async (request: GetPodcastByChatIdRequest) => { - // Validate the request - const parsedRequest = getPodcastByChatIdRequest.safeParse(request); + getPodcastByChatId = async (request: GetPodcastByChatIdRequest) => { + // Validate the request + const parsedRequest = getPodcastByChatIdRequest.safeParse(request); - if (!parsedRequest.success) { - console.error("Invalid request:", parsedRequest.error); + if (!parsedRequest.success) { + console.error("Invalid request:", parsedRequest.error); - // Format a user frendly error message - const errorMessage = parsedRequest.error.errors - .map((err) => err.message) - .join(", "); - throw new ValidationError(`Invalid request: ${errorMessage}`); - } + // Format a user frendly error message + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } - return baseApiService.get( - `/api/v1/podcasts/by-chat/${request.chat_id}`, - podcast - ); - }; + return baseApiService.get(`/api/v1/podcasts/by-chat/${request.chat_id}`, podcast); + }; - generatePodcast = async (request: GeneratePodcastRequest) => { - // Validate the request - const parsedRequest = generatePodcastRequest.safeParse(request); + generatePodcast = async (request: GeneratePodcastRequest) => { + // Validate the request + const parsedRequest = generatePodcastRequest.safeParse(request); - if (!parsedRequest.success) { - console.error("Invalid request:", parsedRequest.error); + if (!parsedRequest.success) { + console.error("Invalid request:", parsedRequest.error); - // Format a user frendly error message - const errorMessage = parsedRequest.error.errors - .map((err) => err.message) - .join(", "); - throw new ValidationError(`Invalid request: ${errorMessage}`); - } + // Format a user frendly error message + const errorMessage = parsedRequest.error.errors.map((err) => err.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } - return baseApiService.post(`/api/v1/podcasts/generate`, undefined, { - body: request, - }); - }; + return baseApiService.post(`/api/v1/podcasts/generate`, undefined, { + body: request, + }); + }; - loadPodcast = async ({ - podcast, - controller, - }: { - podcast: Podcast; - controller?: AbortController; - }) => { - return await baseApiService.getBlob( - `/api/v1/podcasts/${podcast.id}/stream`, - { - signal: controller?.signal, - } - ); - }; + loadPodcast = async ({ + podcast, + controller, + }: { + podcast: Podcast; + controller?: AbortController; + }) => { + return await baseApiService.getBlob(`/api/v1/podcasts/${podcast.id}/stream`, { + signal: controller?.signal, + }); + }; } export const podcastsApiService = new PodcastsApiService();