buildQuery and parseQuery URL helpers
TypeScript
export type QueryValue = string | number | boolean | null | undefined;
/** Encode flat values and arrays into a query string, skipping null/undefined. */
export function buildQuery(params: Record<string, QueryValue | QueryValue[]>, base = ''): string {
const search = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
const values = Array.isArray(value) ? value : [value];
for (const entry of values) {
if (entry !== null && entry !== undefined) search.append(key, String(entry));
}
}
const query = search.toString();
if (!query || !base) return query || base;
return `${base}${base.includes('?') ? '&' : '?'}${query}`;
}
/** Parse a full URL, a bare query or a hash fragment into URLSearchParams. */
export function parseQuery(input: string): URLSearchParams {
const query = input.includes('?') ? input.slice(input.indexOf('?') + 1) : input.replace(/^#/, '');
return new URLSearchParams(query.split('#')[0]);
}
/** Merge parsed params over defaults; explicit query values win. */
export function mergeQuery(params: URLSearchParams, defaults: Record<string, string>): Record<string, string> {
const merged: Record<string, string> = { ...defaults };
for (const [key, value] of params) merged[key] = value;
return merged;
}