UNPKG

mauss

Version:

lightweight, modular, type-safe utilities

66 lines (65 loc) 2.58 kB
/** * Query string decoder (`qsd`) decodes a query string into an object. It accepts a query string with or without the leading `?` and returns a mapped object of decoded query string * * @param qs query string of a URL with or without the leading `?` * @returns mapped object of decoded query string */ export function qsd(qs) { if (qs[0] === '?') qs = qs.slice(1); if (!qs) return {}; const dec = (s) => { if (!s.trim()) return ''; s = decodeURIComponent(s); if (['true', 'false'].includes(s)) return s[0] === 't'; return Number.isNaN(Number(s)) ? s : Number(s); }; const dqs = {}; const qar = qs.split('&'); for (let i = 0; i < qar.length; i++) { const [k, v] = qar[i].split('='); if (v === undefined) continue; const item = dqs[k]; // satisfy TS if (!dqs[k] && (dqs[k] = dec(v))) continue; if (!Array.isArray(item)) dqs[k] = [item]; dqs[k].push(dec(v)); } return dqs; } /** * Query string encoder (`qse`) encodes key-value pairs from an object into a query string. It optionally accepts a second argument for a transformer function that will be applied to the final value if it exists, else an empty string will be returned * * @param bound object with key-value pair to be updated in the URL, only accepts an object with nullish and primitive literals or an array of those values * @param transformer function that is applied to the final string if it exists, useful in cases where we want to add a leading `?` when the query exists but not when it's empty, or when we would like to append another existing query string after only if the output of `qse` exists * @returns final query string */ export function qse(bound, transformer = (final) => `?${final}`) { const enc = encodeURIComponent; let final = ''; for (let [k, v] of Object.entries(bound)) { if (v == null || (typeof v === 'string' && !(v = v.trim()))) continue; if ((k = enc(k)) && final) final += '&'; if (Array.isArray(v)) { let pointer = 0; while (pointer < v.length) { if (pointer) final += '&'; const item = v[pointer++]; if (item == null) continue; final += `${k}=${enc(item)}`; } continue; } final += `${k}=${enc(v)}`; } return final ? transformer(final) : final; }