Home Reference Source

src/lib/convert-data.js

/**
 * Create query portion of url for serialize method
 * @param {string} name
 * @param {object|Array|string} data
 * @returns {string} - part of url
 */
export function getQueryPart(name, data) {
    if (Array.isArray(data)) {
        return data.reduce((part, value) => part + getQueryPart(`${name}[]`, value), '');
    }

    if (typeof data === 'object') {
        return Object.keys(data).reduce((part, index) => part + getQueryPart(`${name}[${index}]`, data[index]), '');
    }

    return `${name}=${encodeURIComponent(data)}&`;
}

/**
 * Name regexp for conversion to path
 * @type {RegExp}
 */
const NAME = /(\[(\w*)\]|\w*)/gi;

/**
 * Convert input name to path array
 * @param {string} name - input name
 * @returns {Array} - path to value in data object
 */
export function convertNameToPath(name) {
    const path = [];

    let matches = NAME.exec(name);
    while (matches !== null) {
        if (matches.index === NAME.lastIndex) {
            NAME.lastIndex += 1;
        }

        path.push(matches[2] || matches[1]);

        matches = NAME.exec(name);
    }

    return path;
}

/**
 * Convert data object to a value for sending
 * @param {object} data - data object
 * @param {string} type - type of conversion
 * @param {function} FileListType
 * @param {function} FormDataType
 * @returns {string|FormData} - output value
 */
export function convertData(data, type, FileListType = FileList, FormDataType = FormData) {
    let convertedData;

    switch (type) {
        case 'serialize':
            convertedData = Object.keys(data).reduce((query, name) => `${query}${getQueryPart(name, data[name])}`, '');
            return convertedData.length ? convertedData.slice(0, -1) : '';
        case 'formData':
            return Object.keys(data).reduce((formData, name) => {
                if (data[name] instanceof FileListType) {
                    if (data[name].length > 1) {
                        for (let i = 0; i < data[name].length; i += 1) {
                            formData.append(`${name}[${i}]`, data[name][i]);
                        }
                    } else if (data[name].length === 1) {
                        formData.append(name, data[name][0]);
                    }
                } else if (typeof data[name] === 'object') {
                    Object.keys(data[name]).forEach(key => formData.append(`${name}[${key}]`, data[name][key]));
                } else {
                    formData.append(name, data[name]);
                }

                return formData;
            }, new FormDataType());
        case 'json':
        default:
            return JSON.stringify(data);
    }
}