/* eslint-disable query/exhaustive-deps -- False */ import type { DefinedInitialDataOptions, DefinedUseQueryResult, FetchQueryOptions, UndefinedInitialDataOptions, UseMutationOptions, UseMutationResult, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult } from '@tanstack/react-query'; import type { AppError } from '../utils/error'; import { useMutation, usePrefetchQuery, useQuery, useSuspenseQuery } from '@tanstack/react-query'; import { isLauncherError } from '../utils/error'; // this gets overwritten by the consumer project export interface Register { // commands: string[]; // defaultError: Error; } type CommandKeys = Register extends { commands: infer Keys extends ReadonlyArray; } ? Keys[number] : string; type DefaultError = Register extends { defaultError: infer Error; } ? Error : never; type QueryKey = [CommandKeys, ...ReadonlyArray]; declare module '@tanstack/react-query' { interface Register { queryKey: QueryKey; mutationKey: QueryKey; } } async function fetchCommand(command: () => Promise): Promise { try { const result = await command(); return result; } // TODO: (lynith) handle errors better (requires modifications to TauRPC) catch (e) { console.error('[fetch]', e); if (isLauncherError(e)) return Promise.reject(e); else return Promise.reject(e); } } type OmittedOptions = Omit; export function useCommand( cacheKey: TQueryKey, command: () => Promise, options: OmittedOptions>, ): DefinedUseQueryResult; export function useCommand( cacheKey: TQueryKey, command: () => Promise, options?: OmittedOptions>, ): UseQueryResult; export function useCommand( cacheKey: TQueryKey, command: () => Promise, options?: | OmittedOptions> | OmittedOptions>, ) { return useQuery({ queryKey: cacheKey, queryFn: () => fetchCommand(command), enabled: true, ...options, }); } export function usePrefetchedCommand( cacheKey: TQueryKey, command: () => Promise, options?: OmittedOptions>, ) { return usePrefetchQuery({ queryKey: cacheKey, queryFn: () => fetchCommand(command), ...options, }); } export function useCommandSuspense( cacheKey: TQueryKey, command: () => Promise, options?: OmittedOptions>, ): UseSuspenseQueryResult { return useSuspenseQuery({ queryKey: cacheKey, queryFn: () => fetchCommand(command), ...options, }); } export function useCommandMut< TData, TError = DefaultError, TVariables = void, TContext = unknown, >( command: (variables: TVariables) => Promise, options?: Omit< UseMutationOptions, 'mutationFn' >, ): UseMutationResult { return useMutation({ mutationFn: command, ...options, }); }