/** * QueryParams Class */ export class QueryParams { /** * NOTE: * This class uses a reducer in order to flatten arrays, this approach is inefficient. * The better solution is to use flatMap when it becomes available. * flatMap is an es2019 proposal in stage 4 (Finished) and should be part of newer TS versions * Angular 8 require a TypeScript update that might include es2019 already. * see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap#Alternative */ private readonly _params: any; constructor(params: any) { if (!(params instanceof Object) || !Object.keys(params)) { throw new Error( 'QueryParams constructor expected an object with at least 1 key' ); } this._params = params; } /** * Converts any value into an array of strings * @param key * @param value */ static serialize(key: string, value: any): string[] { if (typeof value === 'object' && value !== null) { const isArray = value instanceof Array; return (isArray ? value : Object.keys(value)).reduce((acc, cur, idx) => { // TODO: Replace reduce with flatMap (see note above); const { _key, _value } = isArray ? { _key: idx, _value: cur } : { _key: cur, _value: value[cur] }; return acc.concat(QueryParams.serialize(`${key}[${_key}]`, _value)); }, []); } return [`${key}=${encodeURI(value)}`]; } /** * Converts a QueryParams object into an url params string * eg: {a : 1, b : ['a', 'b']} => 'a=1&b[0]=a&b[1]=b' */ toString(): string { let urlParams: string[] = []; for (const key of Object.keys(this._params)) { urlParams = urlParams.concat( QueryParams.serialize(key, this._params[key]) ); } return urlParams.join('&'); } add(key: string, value: any): void{ this._params[key] = value; } }