$ npm install @pinojs/redactSmart object redaction for JavaScript applications - safe AND fast!
Redact JS objects with the same API as fast-redact, but uses innovative selective cloning instead of mutating the original. This provides immutability guarantees with performance competitive to fast-redact for real-world usage patterns.
npm install @pinojs/redact
const slowRedact = require('@pinojs/redact')
const redact = slowRedact({
paths: ['headers.cookie', 'headers.authorization', 'user.password']
})
const obj = {
headers: {
cookie: 'secret-session-token',
authorization: 'Bearer abc123',
'x-forwarded-for': '192.168.1.1'
},
user: {
name: 'john',
password: 'secret123'
}
}
console.log(redact(obj))
// Output: {"headers":{"cookie":"[REDACTED]","authorization":"[REDACTED]","x-forwarded-for":"192.168.1.1"},"user":{"name":"john","password":"[REDACTED]"}}
// Original object is completely unchanged:
console.log(obj.headers.cookie) // 'secret-session-token'
Creates a redaction function with the specified options.
string[] (required): An array of strings describing the nested location of a key in an objectany (optional, default: '[REDACTED]'): The value to replace sensitive data with. Can be a static value or function.Function|boolean (optional, default: JSON.stringify): Serialization function. Set to false to return the redacted object.boolean (optional, default: false): Remove redacted keys from serialized outputboolean (optional, default: true): Throw on non-object values or pass through primitivesSupports the same path syntax as fast-redact:
'user.name', 'headers.cookie''user["password"]', 'headers["X-Forwarded-For"]''users[0].password', 'items[1].secret''users.*.password' (redacts password for all users)'*.password' (redacts password at any level)'items.*' (redacts all array elements)Custom censor value:
const redact = slowRedact({
paths: ['password'],
censor: '***HIDDEN***'
})
Dynamic censor function:
const redact = slowRedact({
paths: ['password'],
censor: (value, path) => `REDACTED:${path}`
})
Return object instead of JSON string:
const redact = slowRedact({
paths: ['secret'],
serialize: false
})
const result = redact({ secret: 'hidden', public: 'data' })
console.log(result.secret) // '[REDACTED]'
console.log(result.public) // 'data'
// Restore original values
const restored = result.restore()
console.log(restored.secret) // 'hidden'
Custom serialization:
const redact = slowRedact({
paths: ['password'],
serialize: obj => JSON.stringify(obj, null, 2)
})
Remove keys instead of redacting:
const redact = slowRedact({
paths: ['password', 'user.secret'],
remove: true
})
const obj = { username: 'john', password: 'secret123', user: { name: 'Jane', secret: 'hidden' } }
console.log(redact(obj))
// Output: {"username":"john","user":{"name":"Jane"}}
// Note: 'password' and 'user.secret' are completely absent, not redacted
Wildcard patterns:
// Redact all properties in secrets object
const redact1 = slowRedact({ paths: ['secrets.*'] })
// Redact password for any user
const redact2 = slowRedact({ paths: ['users.*.password'] })
// Redact all items in an array
const redact3 = slowRedact({ paths: ['items.*'] })
// Remove all secrets instead of redacting them
const redact4 = slowRedact({ paths: ['secrets.*'], remove: true })
serialize: falseremove: true option to completely omit keys from outputserialize: false mode@pinojs/redact uses selective cloning that provides good performance while maintaining immutability guarantees:
| Operation Type | @pinojs/redact | fast-redact | Performance Ratio |
|---|---|---|---|
| Small objects | ~690ns | ~200ns | ~3.5x slower |
| Large objects (minimal redaction) | ~18μs | ~17μs | ~same performance |
| Large objects (wildcards) | ~48μs | ~37μs | ~1.3x slower |
| No redaction (large objects) | ~18μs | ~17μs | ~same performance |
@pinojs/redact is performance-competitive with fast-redact for large objects.
Small Objects (~180 bytes):
Large Objects (~18KB, minimal redaction):
Large Objects (~18KB, wildcard patterns):
Memory Considerations:
Choose fast-redact when:
Choose @pinojs/redact when:
Run benchmarks yourself:
npm run bench
@pinojs/redact uses an innovative selective cloning approach that provides immutability guarantees while dramatically improving performance:
// Old approach: Deep clone entire object, then redact
const fullClone = deepClone(originalObject) // Clone everything
redact(fullClone, paths) // Then redact specific paths
// New approach: Analyze paths, clone only what's needed
const pathStructure = buildPathStructure(paths) // One-time setup
const selectiveClone = cloneOnlyNeededPaths(obj, pathStructure) // Smart cloning
redact(selectiveClone, paths) // Redact pre-identified paths
const largeConfig = {
database: { /* large config object */ },
api: { /* another large config */ },
secrets: { password: 'hidden', apiKey: 'secret' }
}
const redact = slowRedact({ paths: ['secrets.password'] })
const result = redact(largeConfig)
// Only secrets object is cloned, database and api share original references
console.log(result.database === largeConfig.database) // true - shared reference!
console.log(result.api === largeConfig.api) // true - shared reference!
console.log(result.secrets === largeConfig.secrets) // false - cloned for redaction
This approach provides immutability where it matters while sharing references where it's safe.
The remove: true option provides full compatibility with fast-redact's key removal functionality:
const redact = slowRedact({
paths: ['password', 'secrets.*', 'users.*.credentials'],
remove: true
})
const data = {
username: 'john',
password: 'secret123',
secrets: { apiKey: 'abc', token: 'xyz' },
users: [
{ name: 'Alice', credentials: { password: 'pass1' } },
{ name: 'Bob', credentials: { password: 'pass2' } }
]
}
console.log(redact(data))
// Output: {"username":"john","secrets":{},"users":[{"name":"Alice"},{"name":"Bob"}]}
| Option | Behavior | Output Example |
|---|---|---|
| Default (redact) | Replaces values with censor | {"password":"[REDACTED]"} |
remove: true | Completely omits keys | {} |
remove: true*, users.*, items.*.secret)undefined (omitted in JSON output)users.*.credentials.password)JSON.stringify serializer (like fast-redact)# Run unit tests
npm test
# Run integration tests comparing with fast-redact
npm run test:integration
# Run all tests (unit + integration)
npm run test:all
# Run benchmarks
npm run bench
MIT
Pull requests welcome! Please ensure all tests pass and add tests for new features.