diff --git a/src/object/crush.ts b/src/object/crush.ts index 422317b3..3814a2f4 100644 --- a/src/object/crush.ts +++ b/src/object/crush.ts @@ -1,6 +1,4 @@ -import { objectify } from 'radashi' -import { get } from 'radashi' -import { keys } from 'radashi' +import { isDate, isPrimitive, objectify } from 'radashi' /** * Flattens a deep object to a single demension, converting the keys @@ -10,11 +8,34 @@ import { keys } from 'radashi' * crush({ name: 'ra', children: [{ name: 'hathor' }] }) * // { name: 'ra', 'children.0.name': 'hathor' } */ -export const crush = (value: TValue): object => { +type Primitive = + | number + | string + | boolean + | Date + | symbol + | bigint + | undefined + | null + +export const crush = ( + value: TValue +): Record | Record => { if (!value) return {} - return objectify( - keys(value), - k => k, - k => get(value, k) + const crushToPvArray: ( + obj: object, + path: string + ) => Array<{ p: string; v: Primitive }> = (obj: object, path: string) => + Object.entries(obj).flatMap(([key, value]) => + isPrimitive(value) || isDate(value) + ? { p: path === '' ? key : `${path}.${key}`, v: value } + : crushToPvArray(value, path === '' ? key : `${path}.${key}`) + ) + + const result = objectify( + crushToPvArray(value, ''), + o => o.p, + o => o.v ) + return result } diff --git a/src/object/tests/crush.test.ts b/src/object/tests/crush.test.ts index d5509091..77c81f2f 100644 --- a/src/object/tests/crush.test.ts +++ b/src/object/tests/crush.test.ts @@ -33,7 +33,7 @@ describe('crush function', () => { timestamp: now }) }) - test('handles property names with dots', () => { + test('handles property names with dots 1', () => { const obj = { a: { 'b.c': 'value' } } @@ -41,4 +41,28 @@ describe('crush function', () => { 'a.b.c': 'value' }) }) + test('handles property names with dots 2', () => { + const obj = { + 'a.b': { c: 'value' } + } + expect(_.crush(obj)).toEqual({ + 'a.b.c': 'value' + }) + }) + test('handles property names with dots 3', () => { + const obj = { + 'a.b': { 'c.d': 123.4 } + } + expect(_.crush(obj)).toEqual({ + 'a.b.c.d': 123.4 + }) + }) + test('handles arrays', () => { + const obj = ['value', 123.4, true] + expect(_.crush(obj)).toEqual({ + '0': 'value', + '1': 123.4, + '2': true + }) + }) })