Skip to content

Commit

Permalink
Merge branch 'release/v0.20.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
holtwick committed May 2, 2024
2 parents f7cafff + 333223a commit 60fd847
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 16 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.20.3",
"version": "0.20.4",
"description": "🌱 Simple foundation library",
"author": {
"name": "Dirk Holtwick",
Expand Down
42 changes: 35 additions & 7 deletions src/common/data/object.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ describe('objectPlain', () => {
fn.z = 6

class Klass {
name = 'test'
name: string

constructor(name?: string) {
this.name = name ?? 'test'
}
}

const obj = {
Expand All @@ -197,33 +201,51 @@ describe('objectPlain', () => {
['b', 2],
[true, 'bool'],
]),
date: new Date(Date.UTC(2024, 0, 1, 12)),
weakMap: new WeakMap(),
uint8: new Uint8Array([1, 2, 3]),
uint16: new Uint16Array([1, 2, 3]),
c: 2,
d: [3, 4, 5],
Klass,
newKlass: new Klass(),
newKlass: new Klass('testNewKlass'),
},
}

const result = objectPlain(obj, {
keepAsIs: o => o instanceof Uint8Array,
errorTrace: false,
transformer(obj) {
if (obj instanceof Date)
return { __timestamp: obj.getTime() }
},
})

expect(result).toMatchInlineSnapshot(`
Object {
"a": 1,
"b": Object {
"Klass": Object {},
"Klass": Object {
"__class": "Function",
},
"c": 2,
"d": Array [
3,
4,
5,
],
"err": "Error: err",
"date": Object {
"__timestamp": 1704110400000,
},
"err": Object {
"__class": "Error",
"cause": undefined,
"message": "err",
"name": "Error",
"stack": undefined,
},
"fn": Object {
"__class": "Function",
"z": 6,
},
"inf": Infinity,
Expand All @@ -234,9 +256,13 @@ describe('objectPlain', () => {
},
"nan": NaN,
"newKlass": Object {
"name": "test",
"__class": "Klass",
"name": "testNewKlass",
},
"rx": Object {
"__class": "RegExp",
"source": "/.*?.test/gim",
},
"rx": "/.*?.test/gim",
"set": Array [
1,
Object {
Expand All @@ -254,7 +280,9 @@ describe('objectPlain', () => {
2,
3,
],
"weakMap": Object {},
"weakMap": Object {
"__class": "WeakMap",
},
"x": "Symbol(x)",
"y": 123n,
},
Expand Down
58 changes: 50 additions & 8 deletions src/common/data/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export function objectPlain(obj: any, opt?: {
errorTrace?: boolean
filter?: (value: any) => boolean
keepAsIs?: (value: any) => boolean
transformer?: (value: any) => any | undefined
}): any {
const {
maxDepth = 99,
Expand All @@ -69,6 +70,7 @@ export function objectPlain(obj: any, opt?: {
errorTrace = true,
filter = () => true,
keepAsIs = () => false,
transformer = () => undefined,
} = opt ?? {}

const cycle: any = []
Expand All @@ -91,36 +93,76 @@ export function objectPlain(obj: any, opt?: {

cycle.push(obj)

if (obj instanceof Date)
return obj.toISOString()
if (transformer) {
const result = transformer(obj)
if (result !== undefined)
return result
}

if (obj instanceof Date) {
return {
__class: 'Date',
value: obj.toISOString(),
}
}

if (obj instanceof RegExp)
return obj.toString()
if (obj instanceof RegExp) {
return {
__class: 'RegExp',
source: obj.toString(),
}
}

if (obj instanceof Map)
obj = Object.fromEntries(obj)

if (obj instanceof Set || isBinaryArray(obj))
obj = Array.from(obj as any)

if (obj instanceof Error)
return `${obj.name || 'Error'}: ${obj.message}${errorTrace ? `\n${obj.stack}` : ''}`
if (obj instanceof Error) {
return {
__class: 'Error',
name: obj.name,
message: obj.message,
stack: errorTrace ? obj.stack : undefined,
cause: obj.cause ? String(obj.cause) : undefined,
}
}
// return `${obj.name || 'Error'}: ${obj.message}${errorTrace ? `\n${obj.stack}` : ''}`

/* if (obj instanceof Element) {
const attrs = obj.getAttributeNames().map(name => `${name}="${String(obj.getAttribute(name))}"`).join(' ')
return `<${[obj.tagName.toLocaleLowerCase(), ...attrs].join(' ')}}>`
} */

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

// if (isObject(obj) || isFunction(obj)) {
// For class objects just dump the first level of primitives
const objName = obj?.constructor?.name
if (objName && objName !== 'Object') {
const nobj: any = {
__class: objName,
// __code: obj.toString ? obj.toString() : undefined,
}
for (const k in obj) {
if (Object.hasOwn(obj, k) && isPrimitive(obj[k]))
nobj[k] = obj[k]
}
return nobj
}

// Plain objects are recursively dumped
const nobj: any = {}
for (const key in obj) {
const value = obj[key]
if (filter(value))
nobj[key] = handleObject(value, depth + 1)
}
return nobj
// }

// return undefined
}
Expand Down
2 changes: 2 additions & 0 deletions src/common/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { encodeQuery } from './data/url'
import { DefaultLogger } from './log'
import type { Json } from './types'

// TODO: Abort signal https://codedrivendevelopment.com/posts/everything-about-abort-signal-timeout

interface fetchOptionType {
/** Returns the cache mode associated with request, which is a string indicating how the request will interact with the browser's cache when fetching. */
cache?: RequestCache
Expand Down

0 comments on commit 60fd847

Please sign in to comment.