import { isOptional, type Operation } from '@kubb/oas' import { Client } from '@kubb/plugin-client/components' 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, Params } from '@kubb/react-fabric/types' import type { PluginSolidQuery } from '../types.ts' import { MutationKey } from './MutationKey.tsx' type Props = { /** * Name of the function */ name: string typeName: string clientName: string mutationKeyName: string typeSchemas: OperationSchemas operation: Operation dataReturnType: PluginSolidQuery['resolvedOptions']['client']['dataReturnType'] paramsCasing: PluginSolidQuery['resolvedOptions']['paramsCasing'] paramsType: PluginSolidQuery['resolvedOptions']['paramsType'] pathParamsType: PluginSolidQuery['resolvedOptions']['pathParamsType'] } type GetParamsProps = { paramsCasing: PluginSolidQuery['resolvedOptions']['paramsCasing'] pathParamsType: PluginSolidQuery['resolvedOptions']['pathParamsType'] dataReturnType: PluginSolidQuery['resolvedOptions']['client']['dataReturnType'] typeSchemas: OperationSchemas } function getParams({ paramsCasing, dataReturnType, typeSchemas }: GetParamsProps) { const TData = dataReturnType === 'data' ? typeSchemas.response.name : `ResponseConfig<${typeSchemas.response.name}>` const pathParams = getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }) const mutationParams = FunctionParams.factory({ ...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, }) const TRequest = mutationParams.toConstructor() const TError = `ResponseErrorConfig<${typeSchemas.errors?.map((item) => item.name).join(' | ') || 'Error'}>` const generics = [TData, TError, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ') return FunctionParams.factory({ options: { type: ` { mutation?: ReturnType> & { client?: QueryClient }, client?: ${typeSchemas.request?.name ? `Partial> & { client?: Client }` : 'Partial & { client?: Client }'}, } `, default: '{}', }, }) } export function Mutation({ name, clientName, paramsCasing, paramsType, pathParamsType, dataReturnType, typeSchemas, operation, mutationKeyName, }: Props): FabricReactNode { const mutationKeyParams = MutationKey.getParams({ pathParamsType, typeSchemas, }) const params = getParams({ paramsCasing, pathParamsType, dataReturnType, typeSchemas, }) const clientParams = Client.getParams({ paramsCasing, paramsType, typeSchemas, pathParamsType, isConfigurable: true, }) const mutationParams = FunctionParams.factory({ ...getPathParams(typeSchemas.pathParams, { typed: true, casing: paramsCasing }), 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, }) const dataParams = FunctionParams.factory({ data: { // No use of pathParams because useMutation can only take one argument in object form, // see https://tanstack.com/query/latest/docs/framework/react/reference/useMutation#usemutation mode: 'object', children: Object.entries(mutationParams.params).reduce((acc, [key, value]) => { if (value) { acc[key] = { ...value, type: undefined, } } return acc }, {} as Params), }, }) const TRequest = mutationParams.toConstructor() 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, TRequest ? `{${TRequest}}` : 'void', 'TContext'].join(', ') return ( {` const { mutation = {}, client: config = {} } = options ?? {} const { client: queryClient, ...mutationOptions } = mutation; const mutationKey = mutationOptions.mutationKey ?? ${mutationKeyName}(${mutationKeyParams.toCall()}) return useMutation<${generics}>(()=> ({ mutationFn: async(${dataParams.toConstructor()}) => { return ${clientName}(${clientParams.toCall()}) }, mutationKey, ...mutationOptions }), queryClient? () => queryClient: undefined) `} ) }