mirror of https://github.com/buster-so/buster.git
create socket query
This commit is contained in:
parent
51291d44e0
commit
ad02a021ac
|
@ -15,15 +15,22 @@ import { useBusterNotifications } from '@/context/BusterNotifications';
|
|||
import { RustApiError } from './buster_rest/errors';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
|
||||
interface CreateQueryProps<T> extends UseQueryOptions {
|
||||
interface CreateQueryProps<TData, TError = unknown> {
|
||||
queryKey: QueryKey;
|
||||
queryFn: () => Promise<TData>;
|
||||
isUseSession?: boolean;
|
||||
useErrorNotification?: boolean;
|
||||
enabled?: boolean;
|
||||
initialData?: TData;
|
||||
refetchOnWindowFocus?: boolean;
|
||||
refetchOnMount?: boolean;
|
||||
staleTime?: number;
|
||||
options?: Omit<UseQueryOptions<TData, TError, TData>, 'queryKey' | 'queryFn'>;
|
||||
}
|
||||
|
||||
export const PREFETCH_STALE_TIME = 1000 * 10;
|
||||
|
||||
export const useCreateReactQuery = <T>({
|
||||
export const useCreateReactQuery = <TData, TError = unknown>({
|
||||
queryKey,
|
||||
queryFn,
|
||||
isUseSession = true,
|
||||
|
@ -33,13 +40,13 @@ export const useCreateReactQuery = <T>({
|
|||
refetchOnMount = true,
|
||||
useErrorNotification = true,
|
||||
staleTime,
|
||||
...rest
|
||||
}: CreateQueryProps<T>) => {
|
||||
options = {}
|
||||
}: CreateQueryProps<TData, TError>) => {
|
||||
const { openErrorNotification } = useBusterNotifications();
|
||||
const accessToken = useSupabaseContext((state) => state.accessToken);
|
||||
const baseEnabled = isUseSession ? !!accessToken : true;
|
||||
|
||||
const q = useQuery({
|
||||
const q = useQuery<TData, TError>({
|
||||
queryKey: queryKey,
|
||||
queryFn,
|
||||
enabled: baseEnabled && !!enabled,
|
||||
|
@ -48,7 +55,7 @@ export const useCreateReactQuery = <T>({
|
|||
refetchOnWindowFocus,
|
||||
refetchOnMount,
|
||||
staleTime,
|
||||
...rest
|
||||
...options
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -35,7 +35,7 @@ interface BusterSocket {
|
|||
}) => Promise<Parameters<T['callback']>[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 <BusterWebSocket.Provider value={value}>{children}</BusterWebSocket.Provider>;
|
||||
return <BusterWebSocket.Provider value={busterSocketHook}>{children}</BusterWebSocket.Provider>;
|
||||
});
|
||||
BusterWebSocketProvider.displayName = 'BusterWebSocketProvider';
|
||||
|
||||
|
@ -212,7 +212,3 @@ const useBusterWebSocketSelector = <T,>(
|
|||
export const useBusterWebSocket = () => {
|
||||
return useBusterWebSocketSelector((state) => state.busterSocket);
|
||||
};
|
||||
|
||||
export const useBusterWebSocketConnectionStatus = () => {
|
||||
return useBusterWebSocketSelector((state) => state.connectionStatus);
|
||||
};
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import { UseBusterSocketQueryOptions } from './types';
|
||||
|
||||
export const DEFAULT_OPTIONS: Partial<UseBusterSocketQueryOptions<unknown, unknown>> = {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnMount: true,
|
||||
retry: 0,
|
||||
staleTime: 0
|
||||
};
|
|
@ -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');
|
||||
};
|
|
@ -1,3 +0,0 @@
|
|||
export * from './types';
|
||||
export * from './useBusterWebSocketQuery';
|
||||
export * from './helpers';
|
|
@ -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<TRoute extends BusterSocketResponseRoute> = Extract<
|
||||
BusterSocketResponse,
|
||||
{ route: TRoute }
|
||||
>['callback'] extends (d: infer D) => void
|
||||
? D
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Socket response configuration with optional error handler
|
||||
*/
|
||||
export type BusterSocketResponseConfig<TRoute extends BusterSocketResponseRoute> = {
|
||||
route: TRoute;
|
||||
onError?: (d: unknown) => void;
|
||||
};
|
||||
|
||||
export interface UseBusterSocketQueryOptions<TData, TError = unknown>
|
||||
extends Omit<UseQueryOptions<TData, TError>, 'queryKey' | 'queryFn'> {}
|
||||
|
||||
export type UseBusterSocketQueryResult<TData, TError = unknown> = UseQueryResult<TData, TError>;
|
|
@ -203,7 +203,7 @@ export const useUpdateMetricConfig = ({
|
|||
route: '/metrics/update:updateMetricState',
|
||||
callback: onInitializeMetric
|
||||
}
|
||||
}) as Promise<[BusterMetric]>;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './react';
|
||||
export * from './dom';
|
||||
export * from './useDebounceSearch';
|
||||
export * from './useBusterWebSocketQuery';
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import { UseQueryOptions } from '@tanstack/react-query';
|
||||
|
||||
export const DEFAULT_OPTIONS: Partial<UseQueryOptions> = {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnMount: true,
|
||||
retry: 0,
|
||||
staleTime: 0
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from './useBusterWebSocketQuery';
|
|
@ -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<TData, TError = unknown>
|
||||
extends Omit<UseQueryOptions<TData, TError>, 'queryKey' | 'queryFn'> {
|
||||
socketRequest: BusterSocketRequestBase;
|
||||
socketResponse: Omit<BusterSocketResponseBase, 'callback' | 'onError'>;
|
||||
}
|
||||
/**
|
||||
* Infers the response data type from a BusterSocket route
|
||||
*/
|
||||
export type InferBusterSocketResponseData<TRoute extends BusterSocketResponseRoute> = Extract<
|
||||
BusterSocketResponse,
|
||||
{ route: TRoute }
|
||||
>['callback'] extends (d: infer D) => void
|
||||
? D
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Socket response configuration with optional error handler
|
||||
*/
|
||||
export type BusterSocketResponseConfig<TRoute extends BusterSocketResponseRoute> = {
|
||||
route: TRoute;
|
||||
onError?: (d: unknown) => void;
|
||||
};
|
||||
|
||||
export type UseBusterSocketQueryResult<TData, TError = unknown> = UseQueryResult<TData, TError>;
|
||||
|
|
|
@ -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 = <TRoute extends BusterSocketResponseRoute, TError = unknown>(
|
||||
queryKey: QueryKey,
|
||||
socketResponse: BusterSocketResponseConfig<TRoute>
|
||||
): UseBusterSocketQueryResult<InferBusterSocketResponseData<TRoute>, 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<TRoute>);
|
||||
queryClient.invalidateQueries({ queryKey });
|
||||
}
|
||||
} as BusterSocketResponse);
|
||||
});
|
||||
|
||||
return useQuery({
|
||||
queryKey
|
||||
});
|
||||
};
|
||||
|
||||
const ExampleUsage = () => {
|
||||
const { data, isFetched } = useBusterWebSocketOn(['chats', 'get', '123'], {
|
||||
route: '/chats/get:getChat'
|
||||
});
|
||||
};
|
|
@ -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<TRoute extends BusterSocketResponseRoute
|
|||
queryKey: QueryKey,
|
||||
socketRequest: BusterSocketRequest,
|
||||
socketResponse: BusterSocketResponseConfig<TRoute>,
|
||||
options?: UseQueryOptions<InferBusterSocketResponseData<TRoute>, TError>
|
||||
options?: Omit<
|
||||
UseQueryOptions<InferBusterSocketResponseData<TRoute>, TError>,
|
||||
'queryKey' | 'queryFn'
|
||||
>
|
||||
): UseBusterSocketQueryResult<InferBusterSocketResponseData<TRoute>, TError> {
|
||||
const busterSocket = useBusterWebSocket();
|
||||
|
||||
|
@ -39,30 +40,19 @@ export function useBusterWebSocketQuery<TRoute extends BusterSocketResponseRoute
|
|||
}
|
||||
};
|
||||
|
||||
// return useCreateReactQuery<InferBusterSocketResponseData<TRoute>>({
|
||||
// queryKey,
|
||||
// queryFn,
|
||||
// isUseSession: false
|
||||
// });
|
||||
|
||||
return useQuery<
|
||||
InferBusterSocketResponseData<TRoute>,
|
||||
TError,
|
||||
InferBusterSocketResponseData<TRoute>
|
||||
>({
|
||||
return useCreateReactQuery<InferBusterSocketResponseData<TRoute>, 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;
|
||||
};
|
Loading…
Reference in New Issue