diff --git a/web/src/api/createReactQuery.ts b/web/src/api/createReactQuery.ts index abaf140c6..99e565eb4 100644 --- a/web/src/api/createReactQuery.ts +++ b/web/src/api/createReactQuery.ts @@ -15,15 +15,22 @@ import { useBusterNotifications } from '@/context/BusterNotifications'; import { RustApiError } from './buster_rest/errors'; import { useMemoizedFn } from 'ahooks'; -interface CreateQueryProps extends UseQueryOptions { +interface CreateQueryProps { queryKey: QueryKey; + queryFn: () => Promise; isUseSession?: boolean; useErrorNotification?: boolean; + enabled?: boolean; + initialData?: TData; + refetchOnWindowFocus?: boolean; + refetchOnMount?: boolean; + staleTime?: number; + options?: Omit, 'queryKey' | 'queryFn'>; } export const PREFETCH_STALE_TIME = 1000 * 10; -export const useCreateReactQuery = ({ +export const useCreateReactQuery = ({ queryKey, queryFn, isUseSession = true, @@ -33,13 +40,13 @@ export const useCreateReactQuery = ({ refetchOnMount = true, useErrorNotification = true, staleTime, - ...rest -}: CreateQueryProps) => { + options = {} +}: CreateQueryProps) => { const { openErrorNotification } = useBusterNotifications(); const accessToken = useSupabaseContext((state) => state.accessToken); const baseEnabled = isUseSession ? !!accessToken : true; - const q = useQuery({ + const q = useQuery({ queryKey: queryKey, queryFn, enabled: baseEnabled && !!enabled, @@ -48,7 +55,7 @@ export const useCreateReactQuery = ({ refetchOnWindowFocus, refetchOnMount, staleTime, - ...rest + ...options }); useEffect(() => { diff --git a/web/src/context/BusterWebSocket/useBusterWebSocket/useBusterWebSocket.tsx b/web/src/context/BusterWebSocket/useBusterWebSocket/useBusterWebSocket.tsx index 5d4e97020..515b2f4e1 100644 --- a/web/src/context/BusterWebSocket/useBusterWebSocket/useBusterWebSocket.tsx +++ b/web/src/context/BusterWebSocket/useBusterWebSocket/useBusterWebSocket.tsx @@ -35,7 +35,7 @@ interface BusterSocket { }) => Promise[0]>; } -export const useBusterWebSocketHook = ({ +const useBusterWebSocketHook = ({ socketURL, accessToken, checkTokenValidity @@ -195,13 +195,13 @@ export const BusterWebSocketProvider: React.FC<{ const accessToken = useSupabaseContext((state) => state.accessToken); const checkTokenValidity = useSupabaseContext((state) => state.checkTokenValidity); - const value = useBusterWebSocketHook({ + const busterSocketHook = useBusterWebSocketHook({ socketURL: BUSTER_WS_URL, accessToken, checkTokenValidity }); - return {children}; + return {children}; }); BusterWebSocketProvider.displayName = 'BusterWebSocketProvider'; @@ -212,7 +212,3 @@ const useBusterWebSocketSelector = ( export const useBusterWebSocket = () => { return useBusterWebSocketSelector((state) => state.busterSocket); }; - -export const useBusterWebSocketConnectionStatus = () => { - return useBusterWebSocketSelector((state) => state.connectionStatus); -}; diff --git a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/config.ts b/web/src/context/BusterWebSocket/useBusterWebSocketQuery/config.ts deleted file mode 100644 index c9f401316..000000000 --- a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { UseBusterSocketQueryOptions } from './types'; - -export const DEFAULT_OPTIONS: Partial> = { - refetchOnWindowFocus: false, - refetchOnMount: true, - retry: 0, - staleTime: 0 -}; diff --git a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/helpers.ts b/web/src/context/BusterWebSocket/useBusterWebSocketQuery/helpers.ts deleted file mode 100644 index 21b0c15b4..000000000 --- a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/helpers.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { BusterSocketRequest, BusterSocketResponse } from '@/api/buster_socket'; - -export const isSocketError = (error: unknown): error is Error => { - return error instanceof Error; -}; - -export const transformError = (error: unknown): Error => { - if (isSocketError(error)) { - return error; - } - return new Error('Unknown WebSocket error occurred'); -}; diff --git a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/index.ts b/web/src/context/BusterWebSocket/useBusterWebSocketQuery/index.ts deleted file mode 100644 index 02375d503..000000000 --- a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './types'; -export * from './useBusterWebSocketQuery'; -export * from './helpers'; diff --git a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/types.ts b/web/src/context/BusterWebSocket/useBusterWebSocketQuery/types.ts deleted file mode 100644 index d7cb81dd7..000000000 --- a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/types.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { BusterSocketResponse, BusterSocketResponseRoute } from '@/api/buster_socket'; -import { UseQueryOptions, UseQueryResult } from '@tanstack/react-query'; - -/** - * Infers the response data type from a BusterSocket route - */ -export type InferBusterSocketResponseData = Extract< - BusterSocketResponse, - { route: TRoute } ->['callback'] extends (d: infer D) => void - ? D - : never; - -/** - * Socket response configuration with optional error handler - */ -export type BusterSocketResponseConfig = { - route: TRoute; - onError?: (d: unknown) => void; -}; - -export interface UseBusterSocketQueryOptions - extends Omit, 'queryKey' | 'queryFn'> {} - -export type UseBusterSocketQueryResult = UseQueryResult; diff --git a/web/src/context/Metrics/BusterMetricsIndividualProvider/useMetricUpdateConfig.ts b/web/src/context/Metrics/BusterMetricsIndividualProvider/useMetricUpdateConfig.ts index e5545de0f..238dbbea5 100644 --- a/web/src/context/Metrics/BusterMetricsIndividualProvider/useMetricUpdateConfig.ts +++ b/web/src/context/Metrics/BusterMetricsIndividualProvider/useMetricUpdateConfig.ts @@ -203,7 +203,7 @@ export const useUpdateMetricConfig = ({ route: '/metrics/update:updateMetricState', callback: onInitializeMetric } - }) as Promise<[BusterMetric]>; + }); } ); diff --git a/web/src/hooks/index.ts b/web/src/hooks/index.ts index 07396362a..aee9b89fd 100644 --- a/web/src/hooks/index.ts +++ b/web/src/hooks/index.ts @@ -1,3 +1,4 @@ export * from './react'; export * from './dom'; export * from './useDebounceSearch'; +export * from './useBusterWebSocketQuery'; diff --git a/web/src/hooks/useBusterWebSocketQuery/config.ts b/web/src/hooks/useBusterWebSocketQuery/config.ts index a3e8c613e..e69de29bb 100644 --- a/web/src/hooks/useBusterWebSocketQuery/config.ts +++ b/web/src/hooks/useBusterWebSocketQuery/config.ts @@ -1,8 +0,0 @@ -import { UseQueryOptions } from '@tanstack/react-query'; - -export const DEFAULT_OPTIONS: Partial = { - refetchOnWindowFocus: false, - refetchOnMount: true, - retry: 0, - staleTime: 0 -}; diff --git a/web/src/hooks/useBusterWebSocketQuery/index.ts b/web/src/hooks/useBusterWebSocketQuery/index.ts new file mode 100644 index 000000000..dcc130f75 --- /dev/null +++ b/web/src/hooks/useBusterWebSocketQuery/index.ts @@ -0,0 +1 @@ +export * from './useBusterWebSocketQuery'; diff --git a/web/src/hooks/useBusterWebSocketQuery/types.ts b/web/src/hooks/useBusterWebSocketQuery/types.ts index 2a0edb00c..706b04a4d 100644 --- a/web/src/hooks/useBusterWebSocketQuery/types.ts +++ b/web/src/hooks/useBusterWebSocketQuery/types.ts @@ -1,13 +1,22 @@ -import { UseQueryOptions, UseQueryResult } from '@tanstack/react-query'; -import { - BusterSocketRequestBase, - BusterSocketResponseBase -} from '@/api/buster_socket/base_interfaces'; +import type { BusterSocketResponse, BusterSocketResponseRoute } from '@/api/buster_socket'; +import { UseQueryResult } from '@tanstack/react-query'; -export interface UseBusterSocketQueryOptions - extends Omit, 'queryKey' | 'queryFn'> { - socketRequest: BusterSocketRequestBase; - socketResponse: Omit; -} +/** + * Infers the response data type from a BusterSocket route + */ +export type InferBusterSocketResponseData = Extract< + BusterSocketResponse, + { route: TRoute } +>['callback'] extends (d: infer D) => void + ? D + : never; + +/** + * Socket response configuration with optional error handler + */ +export type BusterSocketResponseConfig = { + route: TRoute; + onError?: (d: unknown) => void; +}; export type UseBusterSocketQueryResult = UseQueryResult; diff --git a/web/src/hooks/useBusterWebSocketQuery/useBusterWebSocketOn.tsx b/web/src/hooks/useBusterWebSocketQuery/useBusterWebSocketOn.tsx new file mode 100644 index 000000000..a7b33d6aa --- /dev/null +++ b/web/src/hooks/useBusterWebSocketQuery/useBusterWebSocketOn.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { QueryKey, useQuery, useQueryClient } from '@tanstack/react-query'; +import type { BusterSocketResponse, BusterSocketResponseRoute } from '@/api/buster_socket'; +import { useBusterWebSocket } from '@/context/BusterWebSocket'; +import type { + UseBusterSocketQueryResult, + InferBusterSocketResponseData, + BusterSocketResponseConfig +} from './types'; +import { useMount } from 'ahooks'; + +export const useBusterWebSocketOn = ( + queryKey: QueryKey, + socketResponse: BusterSocketResponseConfig +): UseBusterSocketQueryResult, TError> => { + const busterSocket = useBusterWebSocket(); + const queryClient = useQueryClient(); + + useMount(() => { + busterSocket.on({ + route: socketResponse.route, + onError: socketResponse.onError, + callback: (d: unknown) => { + queryClient.setQueryData(queryKey, d as InferBusterSocketResponseData); + queryClient.invalidateQueries({ queryKey }); + } + } as BusterSocketResponse); + }); + + return useQuery({ + queryKey + }); +}; + +const ExampleUsage = () => { + const { data, isFetched } = useBusterWebSocketOn(['chats', 'get', '123'], { + route: '/chats/get:getChat' + }); +}; diff --git a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/useBusterWebSocketQuery.tsx b/web/src/hooks/useBusterWebSocketQuery/useBusterWebSocketQuery.tsx similarity index 69% rename from web/src/context/BusterWebSocket/useBusterWebSocketQuery/useBusterWebSocketQuery.tsx rename to web/src/hooks/useBusterWebSocketQuery/useBusterWebSocketQuery.tsx index cb70f015a..1c1335eae 100644 --- a/web/src/context/BusterWebSocket/useBusterWebSocketQuery/useBusterWebSocketQuery.tsx +++ b/web/src/hooks/useBusterWebSocketQuery/useBusterWebSocketQuery.tsx @@ -1,13 +1,11 @@ -import { useQuery, QueryKey, UseQueryOptions } from '@tanstack/react-query'; +import { QueryKey, UseQueryOptions } from '@tanstack/react-query'; import type { BusterSocketRequest, BusterSocketResponse, BusterSocketResponseRoute } from '@/api/buster_socket'; -import { useBusterWebSocket } from '../useBusterWebSocket'; -import { transformError } from './helpers'; +import { useBusterWebSocket } from '@/context/BusterWebSocket'; import type { - UseBusterSocketQueryOptions, UseBusterSocketQueryResult, InferBusterSocketResponseData, BusterSocketResponseConfig @@ -18,7 +16,10 @@ export function useBusterWebSocketQuery, - options?: UseQueryOptions, TError> + options?: Omit< + UseQueryOptions, TError>, + 'queryKey' | 'queryFn' + > ): UseBusterSocketQueryResult, TError> { const busterSocket = useBusterWebSocket(); @@ -39,30 +40,19 @@ export function useBusterWebSocketQuery>({ - // queryKey, - // queryFn, - // isUseSession: false - // }); - - return useQuery< - InferBusterSocketResponseData, - TError, - InferBusterSocketResponseData - >({ + return useCreateReactQuery, TError>({ queryKey, queryFn, - ...options + isUseSession: false, + options }); } // Example usage with automatic type inference -export const ExampleUsage = () => { +const ExampleUsage = () => { const { data, isLoading, error } = useBusterWebSocketQuery( ['chats', 'get', '123'], { route: '/chats/get', payload: { id: '123' } }, { route: '/chats/get:getChat' } ); - - useCreateReactQuery; };