From ca989918c06c01c416686202ae8c15522f7ffe4f Mon Sep 17 00:00:00 2001 From: Joel Solano Date: Tue, 21 Oct 2025 19:46:29 +0200 Subject: [PATCH 1/2] feat: add repeatArrayParams option --- packages/better-fetch/src/types.ts | 7 +++++++ packages/better-fetch/src/url.ts | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/better-fetch/src/types.ts b/packages/better-fetch/src/types.ts index 5d9313f..1130ef0 100644 --- a/packages/better-fetch/src/types.ts +++ b/packages/better-fetch/src/types.ts @@ -77,6 +77,13 @@ export type BetterFetchOption< * Query parameters (key-value pairs) */ query?: Query; + /** + * When true, array query parameters are encoded as repeated keys + * (e.g. `?foo=a&foo=b&foo=c`) instead of JSON (`?foo=["a","b","c"]`). + * + * @default false - Arrays are encoded as JSON by default. + */ + repeatArrayParams?: boolean; /** * Dynamic parameters. * diff --git a/packages/better-fetch/src/url.ts b/packages/better-fetch/src/url.ts index 1f9af3d..de52ea6 100644 --- a/packages/better-fetch/src/url.ts +++ b/packages/better-fetch/src/url.ts @@ -32,7 +32,7 @@ export function getURL(url: string, option?: BetterFetchOption) { let serializedValue; if (typeof value === "string") { serializedValue = value; - } else if (Array.isArray(value)) { + } else if (option?.repeatArrayParams && Array.isArray(value)) { for (const val of value) { queryParams.append(key, val); } From 6aed98a7e5244a9df932526d96b37d558d9e4eb6 Mon Sep 17 00:00:00 2001 From: Joel Solano Date: Tue, 21 Oct 2025 19:49:11 +0200 Subject: [PATCH 2/2] chore: update tests --- packages/better-fetch/src/test/fetch.test.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/better-fetch/src/test/fetch.test.ts b/packages/better-fetch/src/test/fetch.test.ts index 5bdde68..1c95b4c 100644 --- a/packages/better-fetch/src/test/fetch.test.ts +++ b/packages/better-fetch/src/test/fetch.test.ts @@ -566,12 +566,13 @@ describe("url", () => { expect(url.toString()).toBe("http://localhost:4001/param/%23test/item%201"); }); - it("should expand array values into multiple query parameters", () => { + it("should expand array values into multiple query parameters when repeatArrayParams is true", () => { const url = getURL("/test", { query: { filterValue: ["admin", "user"], }, baseURL: "http://localhost:4000", + repeatArrayParams: true, }); expect(url.toString()).toBe( @@ -579,6 +580,19 @@ describe("url", () => { ); }); + it("should preserve arrays as JSON strings", () => { + const url = getURL("/test", { + query: { + filterValue: ["admin", "user"], + }, + baseURL: "http://localhost:4000", + }); + + expect(url.toString()).toBe( + "http://localhost:4000/test?filterValue=%5B%22admin%22%2C%22user%22%5D", + ); + }); + it("should preserve objects as JSON strings", () => { const url = getURL("/test", { query: {