emit and once

This commit is contained in:
Nate Kelley 2025-02-13 12:05:16 -07:00
parent da8fd8ba18
commit 7fdae13b7c
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
4 changed files with 126 additions and 36 deletions

View File

@ -93,7 +93,7 @@ export type ChatDeleteChat = BusterSocketRequestBase<
{
/** The unique identifier of the chat to delete */
id: string;
}
}[]
>;
/**

View File

@ -1,4 +1,10 @@
import type { BusterSocketResponse, BusterSocketResponseRoute } from '@/api/buster_socket';
import type {
BusterSocketRequest,
BusterSocketResponse,
BusterSocketResponseRoute
} from '@/api/buster_socket';
//RESPONSE TYPES
export type BusterSocketResponseConfig<TRoute extends BusterSocketResponseRoute> = {
route: TRoute;
@ -14,3 +20,16 @@ export type InferBusterSocketResponseData<TRoute extends BusterSocketResponseRou
>['callback'] extends (d: infer D) => void
? D
: never;
//REQUEST TYPES
export type BusterSocketRequestRoute = BusterSocketRequest['route'];
export type BusterSocketRequestConfig<TRoute extends BusterSocketRequestRoute> = {
route: TRoute;
};
export type InferBusterSocketRequestPayload<TRoute extends BusterSocketRequestRoute> = Extract<
BusterSocketRequest,
{ route: TRoute }
>['payload'];

View File

@ -0,0 +1,79 @@
'use client';
import {
type QueryFunction,
type QueryKey,
type UseQueryOptions,
type UseMutationOptions,
useMutation,
useQueryClient
} from '@tanstack/react-query';
import type {
BusterSocketRequest,
BusterSocketResponse,
BusterSocketResponseRoute
} from '@/api/buster_socket';
import { useBusterWebSocket } from '@/context/BusterWebSocket';
import { useMemoizedFn } from 'ahooks';
import { queryOptionsConfig } from './queryKeyConfig';
import type {
BusterSocketRequestConfig,
BusterSocketRequestRoute,
BusterSocketResponseConfig,
InferBusterSocketRequestPayload,
InferBusterSocketResponseData
} from './types';
export function useSocketMutation<
TRequestRoute extends BusterSocketRequestRoute,
TRoute extends BusterSocketResponseRoute,
TError = unknown,
TData = InferBusterSocketResponseData<TRoute>,
TPayload = InferBusterSocketRequestPayload<TRequestRoute>
>(
socketRequest: BusterSocketRequestConfig<TRequestRoute>,
socketResponse: BusterSocketResponseConfig<TRoute>,
options?: Omit<UseMutationOptions<TData, TError, TPayload>, 'mutationFn'>
) {
const busterSocket = useBusterWebSocket();
const queryClient = useQueryClient();
const mutationFn = useMemoizedFn(async (variables: TPayload): Promise<TData> => {
try {
const result = await busterSocket.emitAndOnce({
emitEvent: {
route: socketRequest.route,
payload: variables
} as BusterSocketRequest,
responseEvent: {
route: socketResponse.route,
onError: socketResponse.onError,
callback: (d: unknown) => d
} as BusterSocketResponse
});
return result as TData;
} catch (error) {
throw error;
}
});
return useMutation<TData, TError, TPayload>({
mutationFn,
...options
});
}
const ExampleComponent = () => {
const { mutate } = useSocketMutation<'/chats/delete', '/chats/delete:deleteChat'>(
{ route: '/chats/delete' },
{ route: '/chats/delete:deleteChat' },
{
onSuccess: (data) => {
console.log(data);
}
}
);
mutate([{ id: '123' }]);
};

View File

@ -1,11 +1,11 @@
'use client';
import {
QueryFunction,
QueryKey,
type QueryFunction,
type QueryKey,
type UseQueryOptions,
useQuery,
useQueryClient,
UseQueryOptions
useQueryClient
} from '@tanstack/react-query';
import type {
BusterSocketRequest,
@ -13,16 +13,10 @@ import type {
BusterSocketResponseRoute
} from '@/api/buster_socket';
import { useBusterWebSocket } from '@/context/BusterWebSocket';
import type {
UseBusterSocketQueryResult,
InferBusterSocketResponseData,
BusterSocketResponseConfig
} from '../useSocketQuery/types';
import { useMemoizedFn } from 'ahooks';
import { createQueryKey } from '../useSocketQuery/helpers';
import { useMemo } from 'react';
import { queryOptionsConfig } from './queryKeyConfig';
import { BusterChat } from '@/api/asset_interfaces';
import type { BusterChat } from '@/api/asset_interfaces';
import { InferBusterSocketResponseData } from './types';
export function useSocketQueryEmitAndOnce<
TRoute extends BusterSocketResponseRoute,
@ -34,34 +28,32 @@ export function useSocketQueryEmitAndOnce<
socketResponse: TRoute,
options: UseQueryOptions<TData, TError, TData, TQueryKey>,
callback?: (currentData: TData | null, newData: InferBusterSocketResponseData<TRoute>) => TData
): UseBusterSocketQueryResult<TData, TError> {
) {
const busterSocket = useBusterWebSocket();
const queryClient = useQueryClient();
const queryFn: QueryFunction<TData> = useMemoizedFn(
async ({ queryKey, ...rest }): Promise<TData> => {
try {
const result = await busterSocket.emitAndOnce({
emitEvent: socketRequest,
responseEvent: {
route: socketResponse,
callback: (d: unknown) => {
const socketData = d as InferBusterSocketResponseData<TRoute>;
if (callback) {
const currentData = queryClient.getQueryData<TData>(queryKey) ?? null;
return callback(currentData, socketData);
}
return socketData as TData;
const queryFn: QueryFunction<TData> = useMemoizedFn(async ({ queryKey }): Promise<TData> => {
try {
const result = await busterSocket.emitAndOnce({
emitEvent: socketRequest,
responseEvent: {
route: socketResponse,
callback: (d: unknown) => {
const socketData = d as InferBusterSocketResponseData<TRoute>;
if (callback) {
const currentData = queryClient.getQueryData<TData>(queryKey) ?? null;
return callback(currentData, socketData);
}
} as BusterSocketResponse
});
return socketData as TData;
}
} as BusterSocketResponse
});
return result as TData;
} catch (error) {
throw error;
}
return result as TData;
} catch (error) {
throw error;
}
);
});
return useQuery({
queryFn,