feat: add makeURLSearchParams utility function (#7744)

This commit is contained in:
A. Román
2022-04-12 17:14:30 +02:00
committed by GitHub
parent 8625d81714
commit 8eaec114a9
13 changed files with 149 additions and 85 deletions

View File

@@ -0,0 +1,60 @@
import { makeURLSearchParams } from '../src';
describe('makeURLSearchParams', () => {
test('GIVEN undefined THEN returns empty URLSearchParams', () => {
const params = makeURLSearchParams();
expect([...params.entries()]).toEqual([]);
});
test('GIVEN empty object THEN returns empty URLSearchParams', () => {
const params = makeURLSearchParams({});
expect([...params.entries()]).toEqual([]);
});
test('GIVEN a record of strings THEN returns URLSearchParams with strings', () => {
const params = makeURLSearchParams({ foo: 'bar', hello: 'world' });
expect([...params.entries()]).toEqual([
['foo', 'bar'],
['hello', 'world'],
]);
});
test('GIVEN a record of strings with nullish values THEN returns URLSearchParams without nullish values', () => {
const params = makeURLSearchParams({ foo: 'bar', hello: null, one: undefined });
expect([...params.entries()]).toEqual([['foo', 'bar']]);
});
test('GIVEN a record of non-string values THEN returns URLSearchParams with string values', () => {
const params = makeURLSearchParams({ life: 42, big: 100n, bool: true });
expect([...params.entries()]).toEqual([
['life', '42'],
['big', '100'],
['bool', 'true'],
]);
});
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(NaN) });
expect([...params.entries()]).toEqual([['before', '2022-04-04T15:43:05.108Z']]);
});
test('GIVEN a record of plain object values THEN returns empty URLSearchParams', () => {
const params = makeURLSearchParams({ foo: {}, hello: { happy: true } });
expect([...params.entries()]).toEqual([]);
});
test('GIVEN a record of objects with overridden toString THEN returns non-empty URLSearchParams', () => {
const params = makeURLSearchParams({ foo: { toString: () => 'bar' } });
expect([...params.entries()]).toEqual([['foo', 'bar']]);
});
});
});

View File

@@ -8,3 +8,4 @@ export * from './lib/errors/RateLimitError';
export * from './lib/RequestManager';
export * from './lib/REST';
export * from './lib/utils/constants';
export { makeURLSearchParams } from './lib/utils/utils';

View File

@@ -2,6 +2,45 @@ import type { RESTPatchAPIChannelJSONBody } from 'discord-api-types/v10';
import type { Response } from 'node-fetch';
import { RequestMethod } from '../RequestManager';
function serializeSearchParam(value: unknown): string | null {
switch (typeof value) {
case 'string':
return value;
case 'number':
case 'bigint':
case 'boolean':
return value.toString();
case 'object':
if (value === null) return null;
if (value instanceof Date) {
return Number.isNaN(value.getTime()) ? null : value.toISOString();
}
// eslint-disable-next-line @typescript-eslint/no-base-to-string
if (typeof value.toString === 'function' && value.toString !== Object.prototype.toString) return value.toString();
return null;
default:
return null;
}
}
/**
* 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
* @returns A populated URLSearchParams instance
*/
export function makeURLSearchParams(options?: Record<string, unknown>) {
const params = new URLSearchParams();
if (!options) return params;
for (const [key, value] of Object.entries(options)) {
const serialized = serializeSearchParam(value);
if (serialized !== null) params.append(key, serialized);
}
return params;
}
/**
* Converts the response to usable data
* @param res The node-fetch response