diff --git a/.changeset/clean-phones-agree.md b/.changeset/clean-phones-agree.md new file mode 100644 index 0000000..40edbf7 --- /dev/null +++ b/.changeset/clean-phones-agree.md @@ -0,0 +1,5 @@ +--- +"@softnetics/hono-react-query": minor +--- + +return client and originalClient from createRQClient diff --git a/src/index.spec.tsx b/src/index.spec.tsx index 58b5452..21f6694 100644 --- a/src/index.spec.tsx +++ b/src/index.spec.tsx @@ -38,6 +38,8 @@ describe('createReactQueryClient', () => { baseUrl: 'http://localhost:3000', }) + expect(client.honoClient).toBeDefined() + expect(client.client).toBeDefined() expect(client.useQuery).toBeDefined() expect(client.useMutation).toBeDefined() expect(client.queryOptions).toBeDefined() @@ -48,6 +50,55 @@ describe('createReactQueryClient', () => { expect(client.useOptimisticUpdateQuery).toBeDefined() }) + describe('client', () => { + const client = createReactQueryClient({ + baseUrl: 'http://localhost:3000', + }) + it('should have typed arguments with return type', () => { + const queryFn = () => client.client('/users/:id', '$get', { param: { id: 'none' } }) + expectTypeOf>().toEqualTypeOf< + Promise< + | { + data: { + user: { + id: string + name: string + } + } + status: 200 + format: 'json' + headers: Record + } + | { + data: { + error: string + } + status: 400 + format: 'json' + headers: Record + } + > + >() + }) + it('should not contain Error when throwOnError is true', () => { + const queryFn = () => + client.client('/users/:id', '$get', { param: { id: 'none' } }, { throwOnError: true }) + expectTypeOf>().toEqualTypeOf< + Promise<{ + data: { + user: { + id: string + name: string + } + } + status: 200 + format: 'json' + headers: Record + }> + >() + }) + }) + describe('useQuery', () => { it('should contain Error in Data when throwOnError is false', () => { const client = createReactQueryClient({ diff --git a/src/index.ts b/src/index.ts index a712f0d..c2da827 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,9 @@ import { HonoResponseError, isHonoResponseError } from './error' import { createQueryKey } from './query-key' import { type Client, + type FlatClientFn, type HonoMutationOptions, + type HonoPayloadOptions, type HonoQueryOptions, type HonoSuspenseQueryOptions, type InferUseHonoQuery, @@ -40,8 +42,11 @@ function createReactQueryClient( : never > { const client = hc(options.baseUrl, options) + const flatClient = flatClientFactory(client) return { + client: flatClient, + honoClient: client, useQuery: useQueryFactory(client), useSuspenseQuery: useSuspenseQueryFactory(client), useMutation: useMutationFactory(client), @@ -94,6 +99,18 @@ async function responseParser(response: Response, throwOnError?: boolean): Promi throw new HonoResponseError(res) } +function flatClientFactory>( + honoClient: Record> +): FlatClientFn { + return (async (path: string, method: string, payload?: any, options?: HonoPayloadOptions) => { + const paths = [...path.toString().split('/').filter(Boolean), method.toString()] + const handler = getter(honoClient, paths) + const throwOnError = options?.throwOnError ?? false // Note: Default to false for flat client + const response = await handler(payload, options) + return responseParser(response, throwOnError) + }) as FlatClientFn +} + function useQueryFactory>( client: Record> ): UseHonoQuery { @@ -259,6 +276,8 @@ function useOptimisticUpdateQueryFactory>() { export { createQueryKey, createReactQueryClient, + type Client as FlatClient, + type FlatClientFn, HonoResponseError, type InferUseHonoQuery, isHonoResponseError, diff --git a/src/types.ts b/src/types.ts index 2b91596..dec7413 100644 --- a/src/types.ts +++ b/src/types.ts @@ -56,7 +56,7 @@ type ErrorResponse = > : never -type HonoPayloadOptions = ClientRequestOptions & { throwOnError?: boolean } +export type HonoPayloadOptions = ClientRequestOptions & { throwOnError?: boolean } export type HonoPayload< TInput, TOptions extends HonoPayloadOptions | undefined = HonoPayloadOptions | undefined, @@ -305,6 +305,8 @@ export type UseHonoOptimisticUpdateQuery> = < | undefined export type ReactQueryClient> = { + honoClient: Record> + client: FlatClientFn useQuery: UseHonoQuery useSuspenseQuery: UseHonoSuspenseQuery useMutation: UseHonoMutation @@ -319,3 +321,21 @@ export type ReactQueryClient> = { export type InferUseHonoQuery> = TQuery extends UseQueryResult ? TData : never + +export type FlatClientFn> = < + TPath extends keyof TApp = keyof TApp, + TMethod extends keyof TApp[TPath] = keyof TApp[TPath], + TPayload extends InferFunctionInput = InferFunctionInput< + TApp[TPath][TMethod] + >, + TOptions extends HonoPayloadOptions | undefined = HonoPayloadOptions | undefined, +>( + path: TPath, + method: TMethod, + payload: TPayload, + options?: TOptions +) => Promise< + TOptions extends { throwOnError: true } + ? SuccessResponse> + : ClientResponseParser> +>