diff --git a/deno_dist/client/client.ts b/deno_dist/client/client.ts index 78ea4150d..238e0a696 100644 --- a/deno_dist/client/client.ts +++ b/deno_dist/client/client.ts @@ -131,9 +131,16 @@ export const hc = >( createProxy((opts) => { const parts = [...opts.path] - let method = '' + let method = '', + $request = false if (/^\$/.test(parts[parts.length - 1])) { - const last = parts.pop() + let last = parts.pop() + + $request = last === '$request' + if ($request) { + last = parts.pop() + } + if (last) { method = last.replace(/^\$/, '') } @@ -149,6 +156,11 @@ export const hc = >( if (method) { options ??= {} const args = deepMerge(options, { ...(opts.args[1] ?? {}) }) + + if ($request) { + return new Request(url, { method, headers: args.headers }) + } + return req.fetch(opts.args[0], args) } return req diff --git a/src/client/client.test.ts b/src/client/client.test.ts index a0f624436..c27ebd948 100644 --- a/src/client/client.test.ts +++ b/src/client/client.test.ts @@ -7,11 +7,11 @@ import { setupServer } from 'msw/node' import _fetch, { Request as NodeFetchRequest } from 'node-fetch' import { vi } from 'vitest' import { Hono } from '../hono' -import { parse, serialize } from '../utils/cookie' +import { parse } from '../utils/cookie' import type { Equal, Expect } from '../utils/types' import { validator } from '../validator' import { hc } from './client' -import type { InferRequestOptionsType, InferRequestType, InferResponseType } from './types' +import type { InferRequestType, InferResponseType } from './types' // @ts-ignore global.fetch = _fetch @@ -517,7 +517,7 @@ describe('Merge path with `app.route()`', () => { .post('/bar', (c) => c.jsonT({ bar: 0 })) const app = new Hono().route('/api', api) type AppType = typeof app - const client = hc('http://localhost') + const client = hc('http://localhost', { headers: { 'x-hono': 'hono' } }) it('Should return correct types - GET /api/foo', async () => { const res = await client.api.foo.$get() @@ -534,6 +534,13 @@ describe('Merge path with `app.route()`', () => { const url = client.api.bar.$url() expect(url.href).toBe('http://localhost/api/bar') }) + it('Should work with $request', async () => { + // @ts-expect-error need a type here + const request = client.api.bar.$post.$request() + expect(request.url).toBe('http://localhost/api/bar') + expect(request.method).toBe('POST') + expect(Object.fromEntries(request.headers)).toStrictEqual({ 'x-hono': 'hono' }) + }) }) }) diff --git a/src/client/client.ts b/src/client/client.ts index 5543d3ae3..48ba541c9 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -131,9 +131,16 @@ export const hc = >( createProxy((opts) => { const parts = [...opts.path] - let method = '' + let method = '', + $request = false if (/^\$/.test(parts[parts.length - 1])) { - const last = parts.pop() + let last = parts.pop() + + $request = last === '$request' + if ($request) { + last = parts.pop() + } + if (last) { method = last.replace(/^\$/, '') } @@ -149,6 +156,11 @@ export const hc = >( if (method) { options ??= {} const args = deepMerge(options, { ...(opts.args[1] ?? {}) }) + + if ($request) { + return new Request(url, { method, headers: args.headers }) + } + return req.fetch(opts.args[0], args) } return req