/** * A censor function receives the original value being redacted plus the dot-path * identifier of where it was found, and returns the value to store in its place. * * Use it for partial masking — e.g. keep the last four digits of a card number, or * mask the local part of an email — instead of a static replacement string. * @example * ```ts * const keepLast4: Censor = (value) => * typeof value === "string" ? "****" + value.slice(-4) : value; * ``` * @param value The original value matched by the rule. * @param path The dot-path of the matched key (e.g. `user.card`), or `undefined` * for matches that have no key path (string-anonymizer / array-index matches). */ type Censor = (value: unknown, path: string | undefined) => unknown; type StringAnonymize = { key: string; pattern: RegExp | string; replacement?: Censor | string; }; type Anonymize = { /** * When `true`, the rule is also applied to nested string values (NLP / regex based), * not just to matching object keys. */ deep?: boolean; /** The key (or wildcard pattern, or NLP type) to match. Case-insensitive. */ key: string; /** Optional regular expression matched against nested string values. */ pattern?: RegExp | string; /** * When `true`, the matching key is deleted from the output object instead of being * replaced with `replacement`. Ignored for array elements and string-anonymizer matches. */ remove?: boolean; /** * The value (or {@link Censor} function) to put in place of a match. Defaults to * the `<KEY>` placeholder when omitted. */ replacement?: unknown; }; type Rules = (Anonymize | StringAnonymize | number | string)[]; type RedactOptions = { exclude?: (number | string)[]; logger?: { debug: (message?: unknown, ...optionalParameters: unknown[]) => void; }; }; /** * Credential / secret rules: API keys, AWS keys, bearer/JWT/Slack tokens, crypto wallets, * basic-auth strings, and the broad key-name rules (`auth`, `password`, `secret`, ...). * * These are the safest default rules — they target high-entropy or unambiguous shapes — and are * what most logger-scrubbing use cases need. */ declare const credentialRules: Rules; /** * Personally-identifiable-information rules: bank accounts, credit cards, IDs/UUIDs, * IPs, MACs, phone numbers, SSNs, NINs, ISBNs, zip codes, URLs/domains, plus the * NLP-powered name/organization/email/money rules. * * WARNING: several of these intentionally match plain numeric data and will overmatch on * ordinary values. For example `bankacc` (`\b\d{10,12}\b`), `id`/`routing` (`\b\d{9}\b`) and * `zip_code` (`\b[0-9]{5}\b`) will redact innocent 5/9/10-12 digit numbers. Use * the `exclude` option (e.g. `{ exclude: ["bankacc", "zip_code"] }`) to drop the * groups you do not need, or compose only the subsets you want. */ declare const piiRules: Rules; /** * Date and time rules. * * WARNING: these match plain weekday names (`monday`, ...), relative words (`today`, * `yesterday`, ...) and common date/time formats, so they will mangle ordinary prose and * numeric data. Most logging use cases should NOT enable these. Drop them via * the `exclude` option or simply compose `credentialRules`/`piiRules` instead. */ declare const dateTimeRules: Rules; /** * The default rule set, aggregating {@link credentialRules}, {@link piiRules} and * {@link dateTimeRules}. * * Note: this set is intentionally aggressive and several rules overmatch ordinary numeric * and prose data (see the warnings on {@link piiRules} and {@link dateTimeRules}). For most * use cases prefer composing only the themed subsets you need, e.g. * `redact(input, [...credentialRules, ...piiRules])`, or use `exclude` to drop noisy groups. */ declare const standardModifierRules: Rules; declare const stringAnonymize: (input: string, modifiers: Rules, options?: RedactOptions) => string; /** * Deep-copies the input and masks sensitive values according to `rules`. Objects, arrays, * `Error`s, `Map`s, `Set`s, JSON strings and URL query strings are all traversed. The input * is never mutated, and circular references are handled. * @example * ```ts * import { redact, standardRules } from "@visulima/redact"; * * redact({ password: "hunter2", user: "alice" }, ["password"]); * // => { password: "", user: "alice" } * * // partial masking with a censor function: * redact({ card: "4111111111111111" }, [ * { key: "card", replacement: (value) => `****${String(value).slice(-4)}` }, * ]); * // => { card: "****1111" } * * // remove a key entirely: * redact({ secret: "x", keep: 1 }, [{ key: "secret", remove: true }]); * // => { keep: 1 } * ``` * @template V The type of the input value; the return type mirrors it. * @param input The value to redact. Returned unchanged for `null`/`undefined`/`number`/`boolean`. * @param rules An array of rules: key names (`string`), array indices (`number`), wildcard * patterns (`"*token*"`), or `Anonymize`/`StringAnonymize` objects with * `pattern`/`replacement`/`remove`. * @param options Optional settings — `exclude` to drop rules by key, and `logger.debug` for tracing. * @returns A redacted deep copy of `input`. */ declare const redact: (input: V, rules: Rules, options?: RedactOptions) => V; /** * Compiles `rules` once and returns a reusable redactor function. Prefer this over calling * {@link redact} repeatedly with the same rule set (e.g. in a logger), since it avoids * re-lowercasing keys and re-compiling patterns on every call. * @example * ```ts * import { createRedactor, standardRules } from "@visulima/redact"; * * const scrub = createRedactor(standardRules); * logger.info(scrub(payload)); * ``` * @param rules The rule set to compile. * @param options Optional settings applied at compile time (`exclude`) and per call (`logger`). * @returns A function `(input) => redactedCopy`. */ declare const createRedactor: (rules: Rules, options?: RedactOptions) => (input: V) => V; export { type Anonymize, type Censor, type RedactOptions, type Rules, type StringAnonymize, createRedactor, credentialRules, dateTimeRules, piiRules, redact, standardModifierRules as standardRules, stringAnonymize };