Skip to content

Commit d9e06cd

Browse files
committed
fix: correctly support array query parameters
1 parent 6fdd2fa commit d9e06cd

File tree

4 files changed

+29
-5
lines changed

4 files changed

+29
-5
lines changed

lib/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,20 @@ export class Client<T extends Route> {
6363
headers.set("content-type", "application/json");
6464
}
6565

66-
const query = new URLSearchParams(options?.query as Record<string, string> ?? {});
66+
const query = new URLSearchParams();
67+
if (options?.query) {
68+
for (const [key, value] of Object.entries(options.query)) {
69+
// NOTE: we cast value to string when assigning to URLSearchParams because
70+
// it handles actually calling .toString() on the values for us
71+
if (Array.isArray(value)) {
72+
for (const v of value) {
73+
query.append(key, v as string);
74+
}
75+
} else {
76+
query.set(key, value as string);
77+
}
78+
}
79+
}
6780

6881
// use server.inject
6982
if (this.#server) {
@@ -93,7 +106,7 @@ export class Client<T extends Route> {
93106
// use a real fetch
94107
const url = new URL(realPath.startsWith("/") ? realPath.slice(1) : realPath, this.#url);
95108
for (const [key, value] of query.entries()) {
96-
url.searchParams.set(key, value);
109+
url.searchParams.append(key, value);
97110
}
98111

99112
const fetchResponse = await fetch(url, {

test/fetch.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ await test("fetch()", async (t) => {
6060
t.assert.equal(withQueryRes.status, 200);
6161
t.assert.equal(withQueryRes.url, `${server.info.uri}/query?flag=true`);
6262
t.assert.deepStrictEqual<SpecificBodyType<routeType, 200>>(withQueryRes.body, { flag: true });
63+
64+
const multiRes = await client.get("/query", { query: { multi: ["one", "three four"] } });
65+
t.assert.equal(multiRes.status, 200);
66+
t.assert.equal(multiRes.url, `${server.info.uri}/query?multi=one&multi=three+four`);
67+
t.assert.deepStrictEqual<SpecificBodyType<routeType, 200>>(multiRes.body, { flag: false, multi: ["one", "three four"] });
6368
});
6469

6570
await t.test("GET /param/{param}", async (t: TestContext) => {

test/fixture.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,16 @@ server.route([
2929
validate: {
3030
query: Joi.object({
3131
flag: Joi.boolean().default(false),
32+
multi: Joi.array().items(Joi.string()),
3233
}),
3334
},
3435
response: {
3536
status: {
36-
200: Joi.object({ flag: Joi.boolean().required() }),
37+
200: Joi.object({ flag: Joi.boolean().required(), multi: Joi.array().items(Joi.string()) }),
3738
},
3839
},
39-
handler(request: Request<{ Query: { flag: boolean } }>) {
40-
return { flag: request.query.flag };
40+
handler(request: Request<{ Query: { flag: boolean; multi?: string[] } }>) {
41+
return { flag: request.query.flag, multi: request.query.multi };
4142
},
4243
},
4344
},

test/inject.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ await test("server.inject()", async (t) => {
2828
t.assert.equal(withQueryRes.status, 200);
2929
t.assert.equal(withQueryRes.url, "/query?flag=true");
3030
t.assert.deepStrictEqual<SpecificBodyType<routeType, 200>>(withQueryRes.body, { flag: true });
31+
32+
const multiRes = await client.get("/query", { query: { multi: ["one", "three four"] } });
33+
t.assert.equal(multiRes.status, 200);
34+
t.assert.equal(multiRes.url, "/query?multi=one&multi=three+four");
35+
t.assert.deepStrictEqual<SpecificBodyType<routeType, 200>>(multiRes.body, { flag: false, multi: ["one", "three four"] });
3136
});
3237

3338
await t.test("GET /param/{param}", async (t: TestContext) => {

0 commit comments

Comments
 (0)