Home Reference Source

lib/util/flatten-result.js

/* eslint-disable no-param-reassign,prefer-destructuring,guard-for-in */
// TODO: rewrite this to not require all these eslint disables.

// TODO: this is like the 2nd or 3rd major revision of this function, using a single
// recursion function. Could probably use a separate "flattenObject" vs "flattenArray" to make
// it simpler.  Right now, I think it's working 100%, though, so I'm not wanting to
// mess with it again.

/** flattenResult does some recursion. We need to act differently on the initial iteration. */
let recursionCount = 0;
/** determine if flattenResult was called with an Array as the root */
let rootWasArray = false;

/**
 * Given an object with arrays inside, reduce any single-length arrays to an object.
 * This is used because the XML output is an array for *everything*, and most of the time you
 * don't want an array for things that will never contain more than one item.
 * If the root of the object is an array, make it an array at the end.
 *
 * This is an attempt to make XML a bit more palatable when converted to JSON.
 * @private
 * @param {any} result
 * @returns same as input, but with single-element arrays reduced to an object
 */

const flattenResult = (result) => {
    // console.warn('**** flattenResult', result);
    // console.warn('* recursionCount=', recursionCount);
    if (recursionCount === 0 && !rootWasArray && Array.isArray(result)) {
        rootWasArray = true;
    }
    recursionCount += 1;
    for (const r in result) {
        // console.warn('**** r=', r);
        if (recursionCount === 0 && Array.isArray(result[r])) {
            result[r] = flattenResult(result[r]);
        } else if (Array.isArray(result[r]) && result[r].length === 1) {
            // console.warn('**** r is single element array');
            result[r] = result[r][0];
        }

        if (typeof result[r] === 'object') {
            // console.warn('**** r is object');
            result[r] = flattenResult(result[r]);
        }
    }
    // console.warn('**** returning ', result);
    if (recursionCount === 0 && rootWasArray === true && !Array.isArray(result)) {
        console.warn('rootWasArray true, result before making array=', result);
        result = [result];
    }
    recursionCount -= 1;
    if (recursionCount === 0) {
        rootWasArray = false;
    }
    return result;
};
/* eslint-enable no-restricted-syntax,no-param-reassign,prefer-destructuring */

// TODO: flattenResult should NOT be called from doRequest() on the entire root, but
// SHOULD be called from the individual functions that dig out what to return. I think.

module.exports = {
    flattenResult,
};