From 422af36d2d6cb8e419eb2e9b33f91b4fb66b7702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Wed, 13 Mar 2024 11:10:44 +0000 Subject: [PATCH] chore: flatten payload util (#6531) https://linear.app/unleash/issue/2-2029/support-filtering-on-nested-properties This will allow us to support and suggest payload subproperties in the action filters. --- src/lib/util/flattenPayload.test.ts | 35 +++++++++++++++++++++++++++++ src/lib/util/flattenPayload.ts | 32 ++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/lib/util/flattenPayload.test.ts create mode 100644 src/lib/util/flattenPayload.ts diff --git a/src/lib/util/flattenPayload.test.ts b/src/lib/util/flattenPayload.test.ts new file mode 100644 index 0000000000..6531a754ff --- /dev/null +++ b/src/lib/util/flattenPayload.test.ts @@ -0,0 +1,35 @@ +import { flattenPayload } from './flattenPayload'; + +describe('flattenPayload', () => { + it('should flatten a payload', () => { + const payload = { + a: 1, + b: { + c: 2, + d: [3, 4], + e: { + f: 5, + }, + }, + }; + expect(flattenPayload(payload)).toEqual({ + a: 1, + 'b.c': 2, + 'b.d[0]': 3, + 'b.d[1]': 4, + 'b.e.f': 5, + }); + }); + + it('should handle conflicting keys gracefully by prioritizing later keys', () => { + const payload = { + a: { + b: 1, + }, + 'a.b': 2, + }; + expect(flattenPayload(payload)).toEqual({ + 'a.b': 2, + }); + }); +}); diff --git a/src/lib/util/flattenPayload.ts b/src/lib/util/flattenPayload.ts new file mode 100644 index 0000000000..78cc6034ff --- /dev/null +++ b/src/lib/util/flattenPayload.ts @@ -0,0 +1,32 @@ +export const flattenPayload = ( + payload = {}, + parentKey = '', +): Record => + Object.entries(payload).reduce((acc, [key, value]) => { + const newKey = parentKey ? `${parentKey}.${key}` : key; + + if ( + typeof value === 'object' && + value !== null && + !Array.isArray(value) + ) { + // If it's an object, recurse and merge the results + Object.assign(acc, flattenPayload(value, newKey)); + } else if (Array.isArray(value)) { + // If it's an array, map through it and handle objects and non-objects differently + value.forEach((item, index) => { + if (typeof item === 'object' && item !== null) { + Object.assign( + acc, + flattenPayload(item, `${newKey}[${index}]`), + ); + } else { + acc[`${newKey}[${index}]`] = item; + } + }); + } else { + acc[newKey] = value; + } + + return acc; + }, {});