import { type EdenRequestParams, type EmptyToVoid, type InferRouteError, type InferRouteOptions, type InferRouteOutput, type ParsedPathAndMethod, } from '@aydee-app/eden' import { type CreateBaseQueryOptions, type CreateQueryOptions, type CreateQueryResult, type DefinedCreateQueryResult, type InitialDataFunction, type SkipToken, skipToken, type StoreOrVal, } from '@tanstack/svelte-query' import type { RouteSchema } from 'elysia' import type { EdenQueryConfig } from '../../config' import type { EdenContextState } from '../../context' import type { DistributiveOmit } from '../../utils/types' import type { EdenQueryBaseOptions } from '../internal/query-base-options' import type { WithEdenQueryExtension } from '../internal/query-hook-extension' import { getQueryKey } from '../internal/query-key' export type EdenCreateQueryOptions< TOutput, TData, TError, TQueryOptsData = TOutput, > = DistributiveOmit< CreateBaseQueryOptions, 'queryKey' > & EdenQueryBaseOptions export type EdenDefinedCreateQueryOptions< TOutput, TData, TError, TQueryOptsData = TOutput, > = DistributiveOmit< CreateBaseQueryOptions, 'queryKey' > & EdenQueryBaseOptions & { initialData: InitialDataFunction | TQueryOptsData } export type EdenCreateQueryResult = WithEdenQueryExtension< CreateQueryResult > export type EdenDefinedCreateQueryResult = WithEdenQueryExtension< DefinedCreateQueryResult > export interface EdenCreateQuery< TRoute extends RouteSchema, _TPath extends any[] = [], // The publicly exposed `createQuery` hook only accepts the `query` object. TInput = InferRouteOptions['query'], TOutput = InferRouteOutput, TError = InferRouteError, > { ( input: StoreOrVal>, options: EdenDefinedCreateQueryOptions, ): EdenDefinedCreateQueryResult ( input: StoreOrVal | SkipToken>, options?: EdenCreateQueryOptions, ): EdenCreateQueryResult } export function edenCreateQueryOptions( parsedPathsAndMethod: ParsedPathAndMethod, context: EdenContextState, // The internal helper to `createQueryOptions` receives the entire input object, including `query` and `params`. input?: InferRouteOptions | SkipToken, options?: EdenCreateQueryOptions, config?: EdenQueryConfig, ): CreateQueryOptions { const { abortOnUnmount, client, queryClient } = context const { paths, path, method } = parsedPathsAndMethod const isInputSkipToken = input === skipToken && typeof input !== 'object' const queryKey = getQueryKey(paths, isInputSkipToken ? undefined : input, 'query') const defaultOptions = queryClient.getQueryDefaults(queryKey) const initialQueryOptions = { ...defaultOptions, ...options } const { eden, ...queryOptions } = initialQueryOptions const resolvedQueryOptions = { ...queryOptions, queryKey } if (isInputSkipToken) { resolvedQueryOptions.queryFn = input return resolvedQueryOptions } resolvedQueryOptions.queryFn = async (queryFunctionContext) => { const params: EdenRequestParams = { ...config, path, method, options: input, ...eden, } const shouldForwardSignal = config?.abortOnUnmount ?? eden?.abortOnUnmount ?? abortOnUnmount if (shouldForwardSignal) { params.fetch = { ...params.fetch, signal: queryFunctionContext.signal } } const result = await client.query(params) if (result.error != null) { throw result.error } return result.data } return resolvedQueryOptions }