diff --git a/packages/better-fetch/src/test/fetch.test.ts b/packages/better-fetch/src/test/fetch.test.ts index 6c1e6ff..cf23945 100644 --- a/packages/better-fetch/src/test/fetch.test.ts +++ b/packages/better-fetch/src/test/fetch.test.ts @@ -533,4 +533,39 @@ describe("url", () => { }); expect(url.toString()).toBe("http://localhost:4001/param/%23test/item%201"); }); + + it("should expand array values into multiple query parameters", () => { + const url = getURL("/test", { + query: { + filterValue: ["admin", "user"], + }, + baseURL: "http://localhost:4000", + }); + + expect(url.toString()).toBe( + "http://localhost:4000/test?filterValue=admin&filterValue=user", + ); + }); + + it("should preserve objects as JSON strings", () => { + const url = getURL("/test", { + query: { + options: { page: 1, limit: 10 }, + }, + baseURL: "http://localhost:4000", + }); + + expect(url.toString()).toBe( + "http://localhost:4000/test?options=%7B%22page%22%3A1%2C%22limit%22%3A10%7D", + ); + }); + + it("should leave strings untouched", () => { + const url = getURL("/test", { + query: { foo: "bar" }, + baseURL: "http://localhost:4000", + }); + + expect(url.toString()).toBe("http://localhost:4000/test?foo=bar"); + }); }); diff --git a/packages/better-fetch/src/url.ts b/packages/better-fetch/src/url.ts index 4a8ad07..1f9af3d 100644 --- a/packages/better-fetch/src/url.ts +++ b/packages/better-fetch/src/url.ts @@ -1,11 +1,11 @@ import { methods } from "./create-fetch"; -import { BetterFetchOption } from "./types"; +import type { BetterFetchOption } from "./types"; /** * Normalize URL */ export function getURL(url: string, option?: BetterFetchOption) { - let { baseURL, params, query } = option || { + const { baseURL, params, query } = option || { query: {}, params: {}, baseURL: "", @@ -29,7 +29,18 @@ export function getURL(url: string, option?: BetterFetchOption) { const queryParams = new URLSearchParams(urlQuery); for (const [key, value] of Object.entries(query || {})) { if (value == null) continue; - queryParams.set(key, String(value)); + let serializedValue; + if (typeof value === "string") { + serializedValue = value; + } else if (Array.isArray(value)) { + for (const val of value) { + queryParams.append(key, val); + } + continue; + } else { + serializedValue = JSON.stringify(value); + } + queryParams.set(key, serializedValue); } if (params) { if (Array.isArray(params)) { @@ -49,7 +60,9 @@ export function getURL(url: string, option?: BetterFetchOption) { if (path.startsWith("/")) path = path.slice(1); let queryParamString = queryParams.toString(); queryParamString = - queryParamString.length > 0 ? `?${queryParamString}`.replace(/\+/g, "%20") : ""; + queryParamString.length > 0 + ? `?${queryParamString}`.replace(/\+/g, "%20") + : ""; if (!basePath.startsWith("http")) { return `${basePath}${path}${queryParamString}`; }