Skip to content

Commit 471ffc4

Browse files
authored
feat: query support array (#25)
* feat: query support array * feat: improve type declaration * docs: update readme about query --------- Co-authored-by: leto.w <[email protected]>
1 parent 9346b90 commit 471ffc4

File tree

6 files changed

+98
-11
lines changed

6 files changed

+98
-11
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,21 @@ type LylaRequestOptions<C = undefined> = {
135135
* `body`.
136136
*/
137137
json?: any
138-
query?: Record<string, string | number>
138+
/**
139+
* Query object, also known as search params.
140+
* Note, if you want to set `null` or `undefined` as value in query,
141+
* use object like `query: { key: "undefined" }` instead of `query: { key: undefined }`.
142+
* Otherwise, the k-v pair will be ignored.
143+
*/
144+
query?: Record<
145+
string,
146+
| string
147+
| number
148+
| boolean
149+
| Array<string | number | boolean>
150+
| null
151+
| undefined
152+
>
139153
baseUrl?: string
140154
/**
141155
* Abort signal of the request.

README.zh_CN.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,21 @@ type LylaRequestOptions<C = undefined> = {
133133
* 需要被写入请求主体的 JSON 值,不可以同时和 body 使用
134134
*/
135135
json?: any
136-
query?: Record<string, string | number>
136+
/**
137+
* Query 对象,用于构建 URL 里的搜索参数 search params。
138+
* 注意,如果你想在查询中设置 `null` 或 `undefined` 作为值,
139+
* 请使用字符串作为值,如 `query: { key: "undefined" }` ,而非 `query: { key: undefined }`。
140+
* 否则,该键值对将被忽略。
141+
*/
142+
query?: Record<
143+
string,
144+
| string
145+
| number
146+
| boolean
147+
| Array<string | number | boolean>
148+
| null
149+
| undefined
150+
>
137151
baseUrl?: string
138152
/**
139153
* 请求使用的 Abort signal

packages/core/src/core.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,15 @@ function isOkStatus(status: number): boolean {
3838

3939
declare const setTimeout: (callback: () => void, timeout?: number) => number
4040

41+
type URLSearchParamsLike = {
42+
toString: () => string
43+
append: (key: string, value: string) => void
44+
}
45+
4146
// It exists both in node, browser, miniprogram environment
4247
declare const URLSearchParams: {
43-
new (params: Record<string, string>): { toString: () => string }
48+
new (params: Record<string, string>): URLSearchParamsLike
49+
new (): URLSearchParamsLike
4450
}
4551

4652
export function createLyla<C, M extends LylaAdapterMeta>(
@@ -164,13 +170,17 @@ export function createLyla<C, M extends LylaAdapterMeta>(
164170

165171
// Resolve query string, patch it to URL
166172
if (_options.query) {
167-
const resolvedQuery: Record<string, string> = {}
168-
for (const key in _options.query) {
169-
const v = _options.query[key]
170-
if (v === undefined || v === null) continue
171-
resolvedQuery[key] = v.toString()
173+
const urlSearchParams = new URLSearchParams()
174+
for (const [key, value] of Object.entries(_options.query)) {
175+
if (Array.isArray(value)) {
176+
for (const v of value) {
177+
urlSearchParams.append(key, v.toString())
178+
}
179+
} else if (value !== undefined && value !== null) {
180+
urlSearchParams.append(key, value.toString())
181+
}
172182
}
173-
const urlSearchParams = new URLSearchParams(resolvedQuery)
183+
174184
const queryString = urlSearchParams.toString()
175185
if (_options.url.includes('?')) {
176186
const badRequestError = defineLylaError<

packages/core/src/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,15 @@ export type LylaRequestOptions<
5353
* `body`.
5454
*/
5555
json?: any
56-
query?: Record<string, string | number | boolean | undefined | null>
56+
query?: Record<
57+
string,
58+
| string
59+
| number
60+
| boolean
61+
| undefined
62+
| null
63+
| Array<string | number | boolean>
64+
>
5765
baseUrl?: string
5866
/**
5967
* Abort signal of the request.

packages/test/server/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ func GetTestRoutes(r *gin.Engine) {
4242
c.Header("X-UPPER", "X-UPPER")
4343
c.Header("x-lower", "x-lower")
4444
})
45+
r.GET("/api/get-query", func(c *gin.Context) {
46+
queryParams := c.Request.URL.Query()
47+
// return {"key1": ["value1"]}
48+
c.JSON(200, queryParams)
49+
})
4550
}
4651

4752
func PostTestRoutes(r *gin.Engine) {

packages/test/tests/basic.spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect, test } from '@playwright/test'
22
import { beforeEach } from './utils'
3-
import "./types"
3+
import './types'
44

55
beforeEach(test)
66
;(['get', 'post', 'delete', 'put', 'patch'] as const).forEach((method) => {
@@ -71,3 +71,39 @@ beforeEach(test)
7171
})
7272
}
7373
})
74+
75+
test('parse normal query', async ({ page }) => {
76+
const res = await page.evaluate(async () => {
77+
const res = await window.lyla.get('/api/get-query', {
78+
query: {
79+
key1: 'value1'
80+
}
81+
})
82+
return res.json
83+
})
84+
expect(res).toMatchObject({ key1: ['value1'] })
85+
})
86+
87+
test('parse array query', async ({ page }) => {
88+
const res = await page.evaluate(async () => {
89+
const res = await window.lyla.get('/api/get-query', {
90+
query: {
91+
key1: ['value1', 'value2']
92+
}
93+
})
94+
return res.json
95+
})
96+
expect(res).toMatchObject({ key1: ['value1', 'value2'] })
97+
})
98+
99+
test('parse empty query', async ({ page }) => {
100+
const res = await page.evaluate(async () => {
101+
const res = await window.lyla.get('/api/get-query', {
102+
query: {
103+
key1: null
104+
}
105+
})
106+
return res.json
107+
})
108+
expect(res).toMatchObject({})
109+
})

0 commit comments

Comments
 (0)