redact.redactObject
v0.1.0 latestRedact specified fields in an object by dot-path, applying PCI/GDPR-compliant strategy-aware PII masking with structural sharing.
Redact specified fields in an object by dot-path, applying PCI/GDPR-compliant strategy-aware PII masking with structural sharing.
Signature
function redactObject<T extends object>(obj: T, pathsOrRules: string[] | RedactRule[], strategy?: RedactStrategy): T
Type Definitions:
RedactRule— interfaceRedactStrategy— type
Problem
Objects containing PII fields need selective masking before logging, analytics, or API forwarding. Manual field-by-field masking is verbose, error-prone, and inconsistent. A path-based approach with configurable strategies per field standardizes redaction across the codebase.
How It Works
Creates a shallow clone with structural sharing — only the paths along redacted fields are cloned; unchanged branches share references with the original. Supports three strategies: 'full' (→ '**'), 'partial' (type-aware via matchFieldType routing to email/phone/ip/token redactors), and 'full-preserve-length' (replaces each character with ''). Paths use dot notation for nested access.
Boundaries
- Does not deep-clone the entire object — uses structural sharing for performance.
- Paths that do not exist or point to non-string values are silently skipped.
- Does not support array indexing in paths (e.g. 'users[0].email').
Replaces
Common boilerplate this function replaces:
const clone = JSON.parse(JSON.stringify(obj)); if (clone.email) clone.email = redactEmail(clone.email); if (clone.user?.phone) clone.user.phone = redactPhone(clone.user.phone);
Examples
redact.redactObject({ name: "John", email: "john@example.com" }, ["email"], "partial"); // { name: "John", email: "j***@example.com" }
redact.redactObject({ name: "John", email: "john@example.com", ip: "10.0.0.1" }, ["email", "ip"], "partial"); // { name: "John", email: "j***@example.com", ip: "10.0.0.*" }
redact.redactObject({ name: "John" }, [{ path: "name", strategy: "full" }]); // { name: "***" }
redact.redactObject({ a: "hello" }, ["a"], "full-preserve-length"); // { a: "*****" }
redact.redactObject({ user: { email: "a@b.com" } }, ["user.email"], "partial"); // { user: { email: "a***@b.com" } }
Standards
Caveats
- 'partial' strategy routes through matchFieldType on the last path segment — unrecognized field names fall back to token redaction (keepHead: 1, keepTail: 1).
- Structural sharing means the returned object shares references to unmodified sub-objects with the original.
- Per-field strategy via RedactRule[] overrides the default strategy parameter.
FAQ
How to redact multiple PII fields in a JavaScript object at once?
redact.redactObject(obj, ['email', 'phone', 'ip'], 'partial') applies type-aware masking to each field based on its name.
How to apply different redaction strategies to different fields?
Pass an array of RedactRule objects: redact.redactObject(obj, [{ path: 'email', strategy: 'partial' }, { path: 'name', strategy: 'full' }]).
How to redact nested object fields by dot-path?
Use dot notation: redact.redactObject(obj, ['user.email']) redacts the email field nested inside the user object.
Does redactObject deep-clone the entire object?
No — it uses structural sharing. Only the path segments leading to redacted fields are shallow-cloned. Unchanged branches share references with the original.
What happens if a redaction path does not exist in the object?
Non-existent paths and paths pointing to non-string values are silently skipped — no error is thrown.