fix(makeURLSearchParams): allow arrays (#11578)

* fix: allow arrays

* refactor: comma
This commit is contained in:
Jiralite
2026-07-19 15:44:49 +01:00
committed by GitHub
parent d29e25d24d
commit 974a8c891f
3 changed files with 69 additions and 5 deletions
+17
View File
@@ -42,6 +42,23 @@ describe('makeURLSearchParams', () => {
]);
});
describe('arrays', () => {
test('GIVEN an array THEN defaults to repeated URLSearchParams without nullish values', () => {
const params = makeURLSearchParams({ foo: ['bar', null, undefined, 'baz'], empty: [] });
expect([...params.entries()]).toEqual([
['foo', 'bar'],
['foo', 'baz'],
]);
});
test('GIVEN an array and comma array format THEN returns a comma-separated value without nullish values', () => {
const params = makeURLSearchParams({ foo: ['bar', null, undefined, 'baz'], empty: [] }, { arrayFormat: 'comma' });
expect([...params.entries()]).toEqual([['foo', 'bar,baz']]);
});
});
describe('objects', () => {
test('GIVEN a record of date values THEN URLSearchParams with ISO string values', () => {
const params = makeURLSearchParams({ before: new Date('2022-04-04T15:43:05.108Z'), after: new Date(Number.NaN) });
+46 -4
View File
@@ -34,18 +34,60 @@ function serializeSearchParam(value: unknown): string | null {
}
}
/**
* Options for serializing URL search parameters.
*/
export interface MakeURLSearchParamsOptions {
/**
* How array values should be serialized.
*
* @defaultValue `'repeat'`
* @see {@link https://docs.discord.com/developers/reference#array-query-strings}
*/
arrayFormat?: 'comma' | 'repeat';
}
/**
* Creates and populates an URLSearchParams instance from an object, stripping
* out null and undefined values, while also coercing non-strings to strings.
*
* @param options - The options to use
* @param parameters - The parameters to use
* @param options - The options for serializing URL search parameters
* @returns A populated URLSearchParams instance
*/
export function makeURLSearchParams<OptionsType extends object>(options?: Readonly<OptionsType>) {
export function makeURLSearchParams<ParametersType extends object>(
parameters?: Readonly<ParametersType>,
options: MakeURLSearchParamsOptions = {},
) {
const params = new URLSearchParams();
if (!options) return params;
if (!parameters) return params;
const { arrayFormat = 'repeat' } = options;
for (const [key, value] of Object.entries(parameters)) {
if (Array.isArray(value)) {
const commaSeparatedElements: string[] | null = arrayFormat === 'comma' ? [] : null;
for (const element of value) {
const serialized = serializeSearchParam(element);
if (serialized === null) {
continue;
}
if (commaSeparatedElements) {
commaSeparatedElements.push(serialized);
} else {
params.append(key, serialized);
}
}
if (commaSeparatedElements?.length) {
params.append(key, commaSeparatedElements.join(','));
}
continue;
}
for (const [key, value] of Object.entries(options)) {
const serialized = serializeSearchParam(value);
if (serialized !== null) params.append(key, serialized);
}
+6 -1
View File
@@ -6,7 +6,12 @@ export type * from './lib/interfaces/Handler.js';
export * from './lib/REST.js';
export * from './lib/utils/constants.js';
export * from './lib/utils/types.js';
export { calculateUserDefaultAvatarIndex, makeURLSearchParams, parseResponse } from './lib/utils/utils.js';
export {
calculateUserDefaultAvatarIndex,
makeURLSearchParams,
type MakeURLSearchParamsOptions,
parseResponse,
} from './lib/utils/utils.js';
/**
* The {@link https://github.com/discordjs/discord.js/blob/main/packages/rest#readme | @discordjs/rest} version