import { encode } from 'js-base64'; // Flatten a nested object to params object { field: { text: 'foo' } } => { field.text ='foo' } function flattenParams(data: object, path = ''): object { const params: any = {}; Object.entries(data).forEach(([key, value]) => { const isObject = value !== null && typeof value === 'object' && !Array.isArray(value); const fieldPath = resolvePath(path, key); if (isObject) { const serializedObject = flattenParams(value, fieldPath); Object.assign(params, serializedObject); } else { params[fieldPath] = value; } }); return params; } function resolvePath(path: string, key: string) { return `${path}${path ? '.' : ''}${key}`; } /** * serializes the params object to URLSearchParams, * if isComplexRequest is true and the payload is not serializable as regular URLSearchParams (because of nested fields), * it will serialize the payload into the .r query param exclusively * @param params * @param isComplexRequest * @returns */ export function toURLSearchParams(params: object, isComplexRequest?: boolean) { const flatten = flattenParams(params); // payloads with deep arrays or complex arrays are not serializable as URLSearchParams const isPayloadNonSerializableAsUrlSearchParams = Object.entries( flatten, ).some( ([key, value]) => key.includes('.') || (Array.isArray(value) && value.some((v) => typeof v === 'object')), ); const shouldSerializeToRParam = isComplexRequest && isPayloadNonSerializableAsUrlSearchParams; if (shouldSerializeToRParam) { return new URLSearchParams({ '.r': encode(JSON.stringify(params), true) }); } else { return Object.entries(flatten).reduce((urlSearchParams, [key, value]) => { // inorder to make `foo: [1,2]` turn into `foo=1&foo=2` and not `foo[]=1&foo[]=2` const keyParams = Array.isArray(value) ? value : [value]; keyParams.forEach((param: any) => { if ( param === undefined || param === null || (Array.isArray(value) && typeof param === 'object') ) { return; } urlSearchParams.append(key, param); }); return urlSearchParams; }, new URLSearchParams()); } }