Skip to content

Commit

Permalink
Merge branch 'release/v0.17.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
holtwick committed Mar 13, 2024
2 parents 22be5d6 + 92b871d commit 37ca876
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "zeed",
"type": "module",
"version": "0.17.3",
"version": "0.17.4",
"description": "🌱 Simple foundation library",
"author": {
"name": "Dirk Holtwick",
Expand Down
5 changes: 5 additions & 0 deletions src/common/data/is.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,39 @@ describe('is', () => {
}
const x = new X()
const plain = { hello: 'world' }
function fn() { return 'hello' }

expect(isObject(X)).toBe(false)
expect(isObject(x)).toBe(true)
expect(isObject(plain)).toBe(true)
expect(isObject([])).toBe(true)
expect(isObject(123)).toBe(false)
expect(isObject(new Date())).toBe(true)
expect(isObject(fn)).toBe(false)

expect(isRecord(X)).toBe(false)
expect(isRecord(x)).toBe(true)
expect(isRecord(plain)).toBe(true)
expect(isRecord([])).toBe(false)
expect(isRecord(123)).toBe(false)
expect(isRecord(new Date())).toBe(true)
expect(isRecord(fn)).toBe(false)

expect(isRecordPlain(X)).toBe(false)
expect(isRecordPlain(x)).toBe(false)
expect(isRecordPlain(plain)).toBe(true)
expect(isRecordPlain([])).toBe(false)
expect(isRecordPlain(123)).toBe(false)
expect(isRecordPlain(new Date())).toBe(false)
expect(isRecordPlain(fn)).toBe(false)

expect(isPrimitive(X)).toBe(false)
expect(isPrimitive(x)).toBe(false)
expect(isPrimitive(plain)).toBe(false)
expect(isPrimitive([])).toBe(false)
expect(isPrimitive(123)).toBe(true)
expect(isPrimitive(new Date())).toBe(false)
expect(isPrimitive(fn)).toBe(false)
})

it('should filter', async () => {
Expand Down
75 changes: 74 additions & 1 deletion src/common/data/object.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useDispose } from '../dispose-defer'
import { Emitter } from '../msg/emitter'
import { objectInclusivePick, objectMap, objectMergeDisposable, objectOmit, objectPick } from './object'
import { objectInclusivePick, objectMap, objectMergeDisposable, objectOmit, objectPick, objectPlain } from './object'

describe('object.spec', () => {
it('should map it', async () => {
Expand Down Expand Up @@ -84,3 +84,76 @@ describe('object.spec', () => {
`)
})
})

describe('objectPlain', () => {
it('should return the plain object', () => {
const obj = {
a: 1,
b: {
c: 2,
d: [3, 4],
},
}
const result = objectPlain(obj)
expect(result).toEqual(obj)
})

it('should handle circular references', () => {
const obj: any = {
a: 1,
}
obj.b = obj
const result = objectPlain(obj)
expect(result).toMatchInlineSnapshot(`
Object {
"a": 1,
"b": undefined,
}
`)
})

it('should handle nested objects', () => {
const obj = {
a: 1,
b: {
c: 2,
d: {
e: 3,
},
},
}
const result = objectPlain(obj)
expect(result).toEqual(obj)
})

it('should handle arrays', () => {
const obj = {
a: 1,
b: [2, 3, 4],
}
const result = objectPlain(obj)
expect(result).toEqual(obj)
})

it('should handle max depth', () => {
const obj = {
a: {
b: {
c: {
d: {
e: 1,
},
},
},
},
}
const result = objectPlain(obj, 3)
expect(result).toEqual({
a: {
b: {
c: undefined,
},
},
})
})
})
34 changes: 33 additions & 1 deletion src/common/data/object.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isArray, isObject } from './is'
import { isArray, isObject, isPrimitive } from './is'

/** Like `.map()` for object. Return new key and value or `undefined` to delete. */
export function objectMap<T = any>(
Expand Down Expand Up @@ -52,3 +52,35 @@ export function objectInclusivePick<T extends object, K extends (string | number
export function objectOmit<T extends object, K extends keyof T>(obj: T, ...keys: K[]) {
return Object.fromEntries(Object.entries(obj).filter(([key]) => !keys.includes(key as K))) as Omit<T, K>
}

/// Convert object to plain object with max depth.
export function objectPlain(obj: any, maxDepth = 99): any {
const cycle: any = []

function handleObject(obj: any, depth: number): any {
if (depth >= maxDepth)
return undefined // '*** MAX DEPTH ***'

if (isPrimitive(obj))
return obj

if (cycle.includes(obj))
return undefined // '*** CYCLE ***'

cycle.push(obj)

if (Array.isArray(obj))
return obj.map(o => handleObject(o, depth + 1))

if (isObject(obj)) {
const nobj: any = {}
for (const [key, value] of Object.entries(obj))
nobj[key] = handleObject(value, depth + 1)
return nobj
}

return undefined
}

return handleObject(obj, 0)
}

0 comments on commit 37ca876

Please sign in to comment.