import { getDefaultValue, isOptional, type Operation } from '@kubb/oas' import type { OperationSchemas } from '@kubb/plugin-oas' import { getComments, getPathParams } from '@kubb/plugin-oas/utils' import { File, Function, FunctionParams } from '@kubb/react-fabric' import type { FabricReactNode } from '@kubb/react-fabric/types' import type { PluginSwr } from '../types.ts' import { QueryKey } from './QueryKey.tsx' import { QueryOptions } from './QueryOptions.tsx' type Props = { /** * Name of the function */ name: string queryOptionsName: string queryKeyName: string queryKeyTypeName: string typeSchemas: OperationSchemas paramsCasing: PluginSwr['resolvedOptions']['paramsCasing'] paramsType: PluginSwr['resolvedOptions']['paramsType'] pathParamsType: PluginSwr['resolvedOptions']['pathParamsType'] dataReturnType: PluginSwr['resolvedOptions']['client']['dataReturnType'] operation: Operation } type GetParamsProps = { paramsCasing: PluginSwr['resolvedOptions']['paramsCasing'] paramsType: PluginSwr['resolvedOptions']['paramsType'] pathParamsType: PluginSwr['resolvedOptions']['pathParamsType'] dataReturnType: PluginSwr['resolvedOptions']['client']['dataReturnType'] typeSchemas: OperationSchemas } function getParams({ paramsType, paramsCasing, pathParamsType, dataReturnType, typeSchemas }: GetParamsProps) { const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>` const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>` if (paramsType === 'object') { const pathParams = getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }) const children = { ...pathParams, data: typeSchemas.request?.name ? { type: typeSchemas.request?.name, optional: isOptional(typeSchemas.request?.schema), } : undefined, params: typeSchemas.queryParams?.name ? { type: typeSchemas.queryParams?.name, optional: isOptional(typeSchemas.queryParams?.schema), } : undefined, headers: typeSchemas.headerParams?.name ? { type: typeSchemas.headerParams?.name, optional: isOptional(typeSchemas.headerParams?.schema), } : undefined, } // Check if all children are optional or undefined const allChildrenAreOptional = Object.values(children).every((child) => !child || child.optional) return FunctionParams.factory({ data: { mode: 'object', children, default: allChildrenAreOptional ? '{}' : undefined, }, options: { type: ` { query?: Parameters>[2], client?: ${typeSchemas.request?.name ? `Partial> & { client?: Client }` : 'Partial & { client?: Client }'}, shouldFetch?: boolean, immutable?: boolean } `, default: '{}', }, }) } return FunctionParams.factory({ pathParams: typeSchemas.pathParams?.name ? { mode: pathParamsType === 'object' ? 'object' : 'inlineSpread', children: getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }), default: getDefaultValue(typeSchemas.pathParams?.schema), } : undefined, data: typeSchemas.request?.name ? { type: typeSchemas.request?.name, optional: isOptional(typeSchemas.request?.schema), } : undefined, params: typeSchemas.queryParams?.name ? { type: typeSchemas.queryParams?.name, optional: isOptional(typeSchemas.queryParams?.schema), } : undefined, headers: typeSchemas.headerParams?.name ? { type: typeSchemas.headerParams?.name, optional: isOptional(typeSchemas.headerParams?.schema), } : undefined, options: { type: ` { query?: Parameters>[2], client?: ${typeSchemas.request?.name ? `Partial> & { client?: Client }` : 'Partial & { client?: Client }'}, shouldFetch?: boolean, immutable?: boolean } `, default: '{}', }, }) } export function Query({ name, typeSchemas, queryKeyName, queryKeyTypeName, queryOptionsName, operation, dataReturnType, paramsType, paramsCasing, pathParamsType, }: Props): FabricReactNode { const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>` const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>` const generics = [TData, TError, `${queryKeyTypeName} | null`] const queryKeyParams = QueryKey.getParams({ pathParamsType, typeSchemas, paramsCasing, }) const params = getParams({ paramsCasing, paramsType, pathParamsType, dataReturnType, typeSchemas, }) const queryOptionsParams = QueryOptions.getParams({ paramsCasing, paramsType, pathParamsType, typeSchemas, }) return ( {` const { query: queryOptions, client: config = {}, shouldFetch = true, immutable } = options ?? {} const queryKey = ${queryKeyName}(${queryKeyParams.toCall()}) return useSWR<${generics.join(', ')}>( shouldFetch ? queryKey : null, { ...${queryOptionsName}(${queryOptionsParams.toCall()}), ...(immutable ? { revalidateIfStale: false, revalidateOnFocus: false, revalidateOnReconnect: false } : { }), ...queryOptions } ) `} ) }