Skip to content

Commit

Permalink
feat: add support for collpasing value by constructor name
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Sep 8, 2024
1 parent 1a8dfc4 commit 88c19e6
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 10 deletions.
58 changes: 48 additions & 10 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function tokenizeObject(
config: {
depth: number
showHidden: boolean
collapse: string[]
inspectObjectPrototype: boolean | 'unless-plain-object'
constructorName?: string
membersToIgnore?: (string | symbol)[]
Expand All @@ -47,23 +48,41 @@ export function tokenizeObject(
}

/**
* Track seen object and increment depth
*/
parser.context.depth++
parser.context.objectsSeen.add(value)

/**
* Keep reference of the config properties
* Keep reference of the config properties to avoid
* property access inside the for loop
*/
const showHidden = config.showHidden

/**
* Grab metadata of the object.
*/
const name = config.constructorName ?? Object.getPrototypeOf(value)?.constructor.name ?? null

/**
* Do not inspect children when constructor of the
* object is meant to be collapsed.
*/
if (config.collapse.includes(name)) {
parser.collect({
type: 'collapse',
name: name,
token: {
type: 'object-start',
constructorName: name,
},
})
return
}

const ownKeys = Reflect.ownKeys(value)
const eagerGetters = config.eagerGetters ?? []

/**
* Track seen object and increment depth
*/
parser.context.depth++
parser.context.objectsSeen.add(value)

/**
* Create a final collection of keys.
*
Expand Down Expand Up @@ -272,6 +291,7 @@ export function tokenizeArray(
config: {
name?: string
depth: number
collapse: string[]
inspectArrayPrototype: boolean
maxArrayLength: number
}
Expand All @@ -292,15 +312,33 @@ export function tokenizeArray(
return
}

const limit = config.maxArrayLength
const size = values.length
const name = config.name || values.constructor.name

/**
* Do not inspect children when constructor of the
* array is meant to be collapsed.
*/
if (config.collapse.includes(name)) {
parser.collect({
type: 'collapse',
name: name,
token: {
type: 'array-start',
name,
size,
},
})
return
}

/**
* Track seen array and increment depth
*/
parser.context.depth++
parser.context.arraysSeen.add(values)

const limit = config.maxArrayLength
const size = values.length
const name = config.name || values.constructor.name
parser.collect({ type: 'array-start', name, size })

for (let index = 0; index < size; index++) {
Expand Down
1 change: 1 addition & 0 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class Parser {
inspectStaticMembers: false,
maxArrayLength: 100,
maxStringLength: 1000,
collapse: [],
...config,
})
}
Expand Down
1 change: 1 addition & 0 deletions src/tokenizers/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export const tokenizers: Partial<Record<TypeName, Tokenizer>> = {
showHidden: true,
depth: parser.config.depth,
inspectObjectPrototype: false,
collapse: parser.config.collapse,
membersToIgnore: ['prototype', 'name', 'length'],
})

Expand Down
24 changes: 24 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,24 @@ export type TokensMap = {
'generator': {
isAsync: boolean
}

/**
* Collapse token represents a value that has been
* collpased and its children are not further
* processed.
*
* Only objects and arrays can be collapsed
*/
'collapse': {
name: string
token:
| ({
type: 'object-start'
} & TokensMap['object-start'])
| ({
type: 'array-start'
} & TokensMap['array-start'])
}
}

/**
Expand Down Expand Up @@ -272,4 +290,10 @@ export type ParserConfig = {
* Defaults to 1000
*/
maxStringLength?: number

/**
* An array of values that must be collapsed. The objects and
* arrays constructor names are checked against these values.
*/
collapse?: string[]
}
44 changes: 44 additions & 0 deletions tests/parser/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,4 +582,48 @@ test.group('Parser | Array', () => {
]
`)
})

test('collapse values by their constructor name', ({ expect }) => {
const parser = new Parser({
collapse: ['Collection'],
})
class Collection extends Array {}

parser.parse({
users: new Collection(),
})

expect(parser.flush()).toMatchInlineSnapshot(`
[
{
"constructorName": "Object",
"type": "object-start",
},
{
"isSymbol": false,
"isWritable": true,
"type": "object-key",
"value": "users",
},
{
"type": "object-value-start",
},
{
"name": "Collection",
"token": {
"name": "Collection",
"size": 0,
"type": "array-start",
},
"type": "collapse",
},
{
"type": "object-value-end",
},
{
"type": "object-end",
},
]
`)
})
})
Loading

0 comments on commit 88c19e6

Please sign in to comment.