mirror of
https://github.com/honojs/hono.git
synced 2024-11-24 19:26:56 +01:00
fix(client): return query params in $url (#3541)
This commit is contained in:
parent
267186d65e
commit
3d8abbc239
@ -847,6 +847,27 @@ describe('$url() with a param option', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('$url() with a query option', () => {
|
||||||
|
const app = new Hono().get(
|
||||||
|
'/posts',
|
||||||
|
validator('query', () => {
|
||||||
|
return {} as { filter: 'test' }
|
||||||
|
}),
|
||||||
|
(c) => c.json({ ok: true })
|
||||||
|
)
|
||||||
|
type AppType = typeof app
|
||||||
|
const client = hc<AppType>('http://localhost')
|
||||||
|
|
||||||
|
it('Should return the correct path - /posts?filter=test', async () => {
|
||||||
|
const url = client.posts.$url({
|
||||||
|
query: {
|
||||||
|
filter: 'test',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(url.search).toBe('?filter=test')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('Client can be awaited', () => {
|
describe('Client can be awaited', () => {
|
||||||
it('Can be awaited without side effects', async () => {
|
it('Can be awaited without side effects', async () => {
|
||||||
const client = hc('http://localhost')
|
const client = hc('http://localhost')
|
||||||
|
@ -4,6 +4,7 @@ import { serialize } from '../utils/cookie'
|
|||||||
import type { UnionToIntersection } from '../utils/types'
|
import type { UnionToIntersection } from '../utils/types'
|
||||||
import type { Callback, Client, ClientRequestOptions } from './types'
|
import type { Callback, Client, ClientRequestOptions } from './types'
|
||||||
import {
|
import {
|
||||||
|
buildSearchParams,
|
||||||
deepMerge,
|
deepMerge,
|
||||||
mergePath,
|
mergePath,
|
||||||
removeIndexString,
|
removeIndexString,
|
||||||
@ -49,20 +50,7 @@ class ClientRequestImpl {
|
|||||||
) => {
|
) => {
|
||||||
if (args) {
|
if (args) {
|
||||||
if (args.query) {
|
if (args.query) {
|
||||||
for (const [k, v] of Object.entries(args.query)) {
|
this.queryParams = buildSearchParams(args.query)
|
||||||
if (v === undefined) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
this.queryParams ||= new URLSearchParams()
|
|
||||||
if (Array.isArray(v)) {
|
|
||||||
for (const v2 of v) {
|
|
||||||
this.queryParams.append(k, v2)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.queryParams.set(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.form) {
|
if (args.form) {
|
||||||
@ -172,10 +160,16 @@ export const hc = <T extends Hono<any, any, any>>(
|
|||||||
const path = parts.join('/')
|
const path = parts.join('/')
|
||||||
const url = mergePath(baseUrl, path)
|
const url = mergePath(baseUrl, path)
|
||||||
if (method === 'url') {
|
if (method === 'url') {
|
||||||
if (opts.args[0] && opts.args[0].param) {
|
let result = url
|
||||||
return new URL(replaceUrlParam(url, opts.args[0].param))
|
if (opts.args[0]) {
|
||||||
|
if (opts.args[0].param) {
|
||||||
|
result = replaceUrlParam(url, opts.args[0].param)
|
||||||
|
}
|
||||||
|
if (opts.args[0].query) {
|
||||||
|
result = result + '?' + buildSearchParams(opts.args[0].query).toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new URL(url)
|
return new URL(result)
|
||||||
}
|
}
|
||||||
if (method === 'ws') {
|
if (method === 'ws') {
|
||||||
const webSocketUrl = replaceUrlProtocol(
|
const webSocketUrl = replaceUrlProtocol(
|
||||||
|
@ -38,7 +38,11 @@ export type ClientRequest<S extends Schema> = {
|
|||||||
$url: (
|
$url: (
|
||||||
arg?: S[keyof S] extends { input: infer R }
|
arg?: S[keyof S] extends { input: infer R }
|
||||||
? R extends { param: infer P }
|
? R extends { param: infer P }
|
||||||
? { param: P }
|
? R extends { query: infer Q }
|
||||||
|
? { param: P; query: Q }
|
||||||
|
: { param: P }
|
||||||
|
: R extends { query: infer Q }
|
||||||
|
? { query: Q }
|
||||||
: {}
|
: {}
|
||||||
: {}
|
: {}
|
||||||
) => URL
|
) => URL
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
buildSearchParams,
|
||||||
deepMerge,
|
deepMerge,
|
||||||
mergePath,
|
mergePath,
|
||||||
removeIndexString,
|
removeIndexString,
|
||||||
@ -59,6 +60,18 @@ describe('replaceUrlParams', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('buildSearchParams', () => {
|
||||||
|
it('Should build URLSearchParams correctly', () => {
|
||||||
|
const query = {
|
||||||
|
id: '123',
|
||||||
|
type: 'test',
|
||||||
|
tag: ['a', 'b'],
|
||||||
|
}
|
||||||
|
const searchParams = buildSearchParams(query)
|
||||||
|
expect(searchParams.toString()).toBe('id=123&type=test&tag=a&tag=b')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('replaceUrlProtocol', () => {
|
describe('replaceUrlProtocol', () => {
|
||||||
it('Should replace http to ws', () => {
|
it('Should replace http to ws', () => {
|
||||||
const url = 'http://localhost'
|
const url = 'http://localhost'
|
||||||
|
@ -15,6 +15,26 @@ export const replaceUrlParam = (urlString: string, params: Record<string, string
|
|||||||
return urlString
|
return urlString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const buildSearchParams = (query: Record<string, string | string[]>) => {
|
||||||
|
const searchParams = new URLSearchParams()
|
||||||
|
|
||||||
|
for (const [k, v] of Object.entries(query)) {
|
||||||
|
if (v === undefined) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
for (const v2 of v) {
|
||||||
|
searchParams.append(k, v2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
searchParams.set(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchParams
|
||||||
|
}
|
||||||
|
|
||||||
export const replaceUrlProtocol = (urlString: string, protocol: 'ws' | 'http') => {
|
export const replaceUrlProtocol = (urlString: string, protocol: 'ws' | 'http') => {
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case 'ws':
|
case 'ws':
|
||||||
|
Loading…
Reference in New Issue
Block a user