BBizKit

redact.redactObject

v0.1.0 latest

Redact specified fields in an object by dot-path, applying PCI/GDPR-compliant strategy-aware PII masking with structural sharing.

redactobjectpiigdprmaskingpath-basedstructural-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:

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.