@medusajs/utils
Version:
Medusa utilities functions shared by Medusa core and Modules
267 lines (263 loc) • 10.4 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.flattenObjectToKeyValuePairs = flattenObjectToKeyValuePairs;
const is_object_1 = require("./is-object");
/*
Given a deeply nested object that can be arrays or objects, this function will flatten
it to an object that is 1 level deep.
Given an object: testObject = {
product: {
id: "test-product",
name: "Test Product",
categories: [{
id: "test-category",
name: "Test Category"
}]
}
}
flattenObjectToKeyValuePairs(testObject) will return
{
"product.id": "test-product",
"product.name": "Test Product",
"product.categories.id": ["test-category"],
"product.categories.name": ["Test Category"]
}
Null and undefined values are excluded from the result.
*/
function flattenObjectToKeyValuePairs(obj) {
const result = {};
function shouldPreserveArray(value, path) {
if (!Array.isArray(value) || value.length === 0) {
return false;
}
if (value.some((item) => (0, is_object_1.isObject)(item) && !Array.isArray(item))) {
return true;
}
if (value.some((item) => Array.isArray(item))) {
return true;
}
if (path.length > 1) {
return true;
}
if (value.length > 1) {
const firstType = typeof value[0];
const allSameType = value.every((item) => typeof item === firstType && !(0, is_object_1.isObject)(item) && !Array.isArray(item));
if (allSameType) {
return true;
}
}
return false;
}
/**
* Normalize array values - unwrap single-item arrays and handle empty arrays
*/
function normalizeArrayValue(value, path) {
if (!Array.isArray(value)) {
return value;
}
if (value.length === 1 &&
Array.isArray(value[0]) &&
value[0].length === 0) {
return [];
}
if (shouldPreserveArray(value, path)) {
return value;
}
if (value.length === 1 && !(0, is_object_1.isObject)(value[0]) && !Array.isArray(value[0])) {
return value[0];
}
return value;
}
/**
* Recursively process an object/array and flatten it
*/
function processPath(value, currentPath = []) {
// Handle null, undefined, or primitive values
if (!value || typeof value !== "object") {
if (value !== null && value !== undefined && currentPath.length > 0) {
result[currentPath.join(".")] = value;
}
return;
}
if (Array.isArray(value)) {
if (value.length === 0) {
if (currentPath.length > 0) {
result[currentPath.join(".")] = [];
}
return;
}
if (value.some((item) => (0, is_object_1.isObject)(item) && !Array.isArray(item))) {
extractPropertiesFromArray(value, currentPath);
}
else if (value.some((item) => Array.isArray(item))) {
const allValues = [];
const flattenedObjects = [];
const flattenArray = (arr, collector = []) => {
arr.forEach((item) => {
if (Array.isArray(item)) {
flattenArray(item, collector);
}
else if ((0, is_object_1.isObject)(item)) {
collector.push(item);
}
else if (item !== null && item !== undefined) {
allValues.push(item);
}
});
};
flattenArray(value, flattenedObjects);
if (flattenedObjects.length > 0) {
extractPropertiesFromArray(flattenedObjects, currentPath);
}
else if (allValues.length > 0) {
result[currentPath.join(".")] = normalizeArrayValue(allValues, currentPath);
}
}
else {
const cleanedValues = value.filter((v) => v !== null && v !== undefined);
if (cleanedValues.length > 0) {
result[currentPath.join(".")] = normalizeArrayValue(cleanedValues, currentPath);
}
}
return;
}
Object.entries(value).forEach(([key, propValue]) => {
const newPath = [...currentPath, key];
if (propValue === null || propValue === undefined) {
return;
}
else if (Array.isArray(propValue)) {
if (propValue.length === 0) {
result[newPath.join(".")] = [];
}
else {
processPath(propValue, newPath);
}
}
else if ((0, is_object_1.isObject)(propValue)) {
processPath(propValue, newPath);
}
else {
result[newPath.join(".")] = propValue;
}
});
}
/**
* Extract all properties from an array of objects and store them
*/
function extractPropertiesFromArray(array, basePath = []) {
if (!array.length)
return;
// Collect all unique keys from all objects in the array
const allKeys = new Set();
array.forEach((item) => {
if ((0, is_object_1.isObject)(item) && !Array.isArray(item)) {
Object.keys(item).forEach((key) => allKeys.add(key));
}
});
allKeys.forEach((key) => {
const valuePath = [...basePath, key];
const values = [];
array.forEach((item) => {
if ((0, is_object_1.isObject)(item) && !Array.isArray(item) && key in item) {
const itemValue = item[key];
if (itemValue !== null && itemValue !== undefined) {
values.push(itemValue);
}
}
});
if (values.length === 0)
return;
if (values.every((v) => (0, is_object_1.isObject)(v) && !Array.isArray(v))) {
extractNestedObjectProperties(values, valuePath);
}
else if (values.some((v) => Array.isArray(v))) {
if (values.every((v) => Array.isArray(v) && v.length === 0)) {
result[valuePath.join(".")] = [];
}
else {
const flattenedArray = [];
for (const arrayValue of values) {
if (Array.isArray(arrayValue)) {
if (arrayValue.some((v) => (0, is_object_1.isObject)(v) && !Array.isArray(v))) {
extractPropertiesFromArray(arrayValue, valuePath);
}
else {
flattenedArray.push(...arrayValue);
}
}
else {
flattenedArray.push(arrayValue);
}
}
if (flattenedArray.length > 0 &&
!flattenedArray.some((v) => (0, is_object_1.isObject)(v) && !Array.isArray(v))) {
result[valuePath.join(".")] = normalizeArrayValue(flattenedArray, valuePath);
}
}
}
else {
result[valuePath.join(".")] = normalizeArrayValue(values, valuePath);
}
});
}
/**
* Extract properties from nested objects and add them to the result
*/
function extractNestedObjectProperties(objects, basePath = []) {
if (!objects.length)
return;
// Collect all unique keys from all objects
const allNestedKeys = new Set();
objects.forEach((obj) => {
if ((0, is_object_1.isObject)(obj) && !Array.isArray(obj)) {
Object.keys(obj).forEach((key) => allNestedKeys.add(key));
}
});
allNestedKeys.forEach((nestedKey) => {
const nestedPath = [...basePath, nestedKey];
const nestedValues = [];
objects.forEach((obj) => {
if ((0, is_object_1.isObject)(obj) && !Array.isArray(obj) && nestedKey in obj) {
const nestedValue = obj[nestedKey];
if (nestedValue !== null && nestedValue !== undefined) {
nestedValues.push(nestedValue);
}
}
});
if (nestedValues.length === 0)
return;
if (nestedValues.every((v) => (0, is_object_1.isObject)(v) && !Array.isArray(v))) {
extractNestedObjectProperties(nestedValues, nestedPath);
}
else if (nestedValues.some((v) => Array.isArray(v))) {
if (nestedValues.every((v) => Array.isArray(v) && v.length === 0)) {
result[nestedPath.join(".")] = [];
}
else {
const allArrayItems = [];
for (const arrayValue of nestedValues) {
if (Array.isArray(arrayValue)) {
allArrayItems.push(...arrayValue);
}
else {
allArrayItems.push(arrayValue);
}
}
if (allArrayItems.some((item) => (0, is_object_1.isObject)(item) && !Array.isArray(item))) {
extractPropertiesFromArray(allArrayItems, nestedPath);
}
else {
result[nestedPath.join(".")] = normalizeArrayValue(allArrayItems, nestedPath);
}
}
}
else {
result[nestedPath.join(".")] = normalizeArrayValue(nestedValues, nestedPath);
}
});
}
processPath(obj);
return result;
}
//# sourceMappingURL=flatten-object-to-key-value-pairs.js.map
;