Skip to content

feat: Use toJSON for otherwise-empty objects #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions lib/deep-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,18 @@ const deepMap = (input, handler = v => v, path = ['$'], seen = new Set([input]))
} else if (typeof input === 'object' || typeof input === 'function') {
const result = {}

for (const propertyName of Object.getOwnPropertyNames(input)) {
// skip logging internal properties
if (propertyName.startsWith('_')) {
continue
const publicPropertyNames = Object.getOwnPropertyNames(input).filter((name) => !name.startsWith('_'))

// if there are no public properties, check for custom serialization
if (publicPropertyNames.length === 0 && typeof input.toJSON === 'function') {
try {
return handler(input.toJSON(), path)
} catch (err) {
return `[error getting JSON value: ${err.message}]`
}
}

for (const propertyName of publicPropertyNames) {
try {
const property = input[propertyName]
const propertyPath = [...path, propertyName]
Expand Down
8 changes: 8 additions & 0 deletions tap-snapshots/test/suite/server-redact-nonstring.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ exports[`test/suite.js TAP server redact nonstring nonString emptyObject just se
Object {}
`

exports[`test/suite.js TAP server redact nonstring nonString exampleCustomSerializerThrows just serverRedact > must match snapshot 1`] = `
[error getting JSON value: Error in toJSON]
`

exports[`test/suite.js TAP server redact nonstring nonString exampleGetterThrows just serverRedact > must match snapshot 1`] = `
Object {
"getter": "[error getting value: Error in getter]",
Expand Down Expand Up @@ -148,6 +152,10 @@ Object {
}
`

exports[`test/suite.js TAP server redact nonstring nonStringSensitve exampleCustomSerializer just serverRedact > must match snapshot 1`] = `
latitude: 37.7822689; longitude: -122.3937449; secret: [REDACTED_NPM_SECRET]
`

exports[`test/suite.js TAP server redact nonstring nonStringSensitve exampleGetter just serverRedact > must match snapshot 1`] = `
Object {
"getter": "[REDACTED_NPM_SECRET]",
Expand Down
20 changes: 20 additions & 0 deletions test/fixtures/complex.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ const exampleGetter = (() => {
return example
})()

const exampleCustomSerializer = (() => {
class ExampleClass {
toJSON () {
return `latitude: 37.7822689; longitude: -122.3937449; secret: ${examples.NPM_SECRET.npm_36}`
}
}
return new ExampleClass()
})()

const exampleGetterThrows = (() => {
const example = {}
Object.defineProperty(example, 'getter', {
Expand All @@ -37,6 +46,15 @@ const exampleGetterThrows = (() => {
return example
})()

const exampleCustomSerializerThrows = (() => {
class ExampleClass {
toJSON () {
throw new Error('Error in toJSON')
}
}
return new ExampleClass()
})()

const circular = (() => {
const example = exampleObject
exampleObject.nested = exampleObject
Expand Down Expand Up @@ -64,6 +82,7 @@ const examplesNonString = {
objectNumbers: { a: 1, b: 2, c: 3 },
objectStrings: { a: 'a', b: 'b', c: 'c' },
exampleGetterThrows,
exampleCustomSerializerThrows,
}

const error = (() => {
Expand All @@ -81,6 +100,7 @@ const examplesNonStringSensitive = {
circular,
circularArray,
exampleGetter,
exampleCustomSerializer,
error,
privateProperty: {
...exampleObject,
Expand Down
24 changes: 24 additions & 0 deletions test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,30 @@ t.test('error with buffer', async () => {

t.same(deepMap(new TextEncoder().encode('hello')), '[unable to log instanceof Uint8Array]')

t.test('deepMap date', async (t) => {
const date = new Date('2010-01-12T00:00:00.000Z')
const result = deepMap(date)
t.same(result, '2010-01-12T00:00:00.000Z')
})

t.test('deepMap nested date', async (t) => {
const date = new Date('2010-01-12T00:00:00.000Z')
const result = deepMap({ message: 'npm version 0.0.1 published', date })
t.same(result, ({ message: 'npm version 0.0.1 published', date: '2010-01-12T00:00:00.000Z' }))
})

t.test('deepMap URL', async (t) => {
const url = new URL('https://www.npmjs.com/package/@npmcli/redact?activeTab=versions')
const result = deepMap(url)
t.same(result, 'https://www.npmjs.com/package/@npmcli/redact?activeTab=versions')
})

t.test('deepMap nested URL', async (t) => {
const url = new URL('https://www.npmjs.com/package/@npmcli/redact?activeTab=versions')
const result = deepMap({ message: 'request start', url })
t.same(result, ({ message: 'request start', url: 'https://www.npmjs.com/package/@npmcli/redact?activeTab=versions' }))
})

const redactUrl = redactMatchers(
redactUrlMatcher(
redactUrlHostnameMatcher({ hostname: 'example.com', replacement: 'example.net' }),
Expand Down